@@ -77,19 +77,46 @@ static bool ignore_proc(pid_t pid, bool warn_rootfs) {
77
77
return true;
78
78
}
79
79
80
- static void wait_for_children (Set * pids , sigset_t * mask , usec_t timeout ) {
80
+ static void log_children_no_yet_killed (Set * pids ) {
81
+ void * p ;
82
+ Iterator i ;
83
+ _cleanup_free_ char * lst_child = NULL ;
84
+
85
+ SET_FOREACH (p , pids , i ) {
86
+ _cleanup_free_ char * s = NULL ;
87
+
88
+ if (get_process_comm (PTR_TO_PID (p ), & s ) == 0 ) {
89
+ if (!strextend (& lst_child , ", " , s , NULL ))
90
+ break ;
91
+ }
92
+ }
93
+
94
+ if (!isempty (lst_child ))
95
+ log_notice ("Waiting for process:%s" , lst_child + 1 );
96
+ }
97
+
98
+ static int wait_for_children (Set * pids , sigset_t * mask , usec_t timeout ) {
81
99
usec_t until ;
100
+ usec_t date_log_child ;
101
+ usec_t n ;
82
102
83
103
assert (mask );
84
104
105
+ /* Return the number of children remaining in the pids set: That correspond to the number
106
+ * of processes still "alive" after the timeout */
107
+
85
108
if (set_isempty (pids ))
86
- return ;
109
+ return 0 ;
110
+
111
+ n = now (CLOCK_MONOTONIC );
112
+ until = usec_add (n , timeout );
113
+ date_log_child = usec_add (n , 10u * USEC_PER_SEC );
114
+ if (date_log_child > until )
115
+ date_log_child = usec_add (n , timeout / 2u );
87
116
88
- until = now (CLOCK_MONOTONIC ) + timeout ;
89
117
for (;;) {
90
118
struct timespec ts ;
91
119
int k ;
92
- usec_t n ;
93
120
void * p ;
94
121
Iterator i ;
95
122
@@ -107,8 +134,7 @@ static void wait_for_children(Set *pids, sigset_t *mask, usec_t timeout) {
107
134
if (errno == ECHILD )
108
135
break ;
109
136
110
- log_error_errno (errno , "waitpid() failed: %m" );
111
- return ;
137
+ return log_error_errno (errno , "waitpid() failed: %m" );
112
138
}
113
139
114
140
(void ) set_remove (pids , PID_TO_PTR (pid ));
@@ -130,20 +156,28 @@ static void wait_for_children(Set *pids, sigset_t *mask, usec_t timeout) {
130
156
}
131
157
132
158
if (set_isempty (pids ))
133
- return ;
159
+ return 0 ;
134
160
135
161
n = now (CLOCK_MONOTONIC );
162
+ if (date_log_child > 0 && n >= date_log_child ) {
163
+ log_children_no_yet_killed (pids );
164
+ /* Log the children not yet killed only once */
165
+ date_log_child = 0 ;
166
+ }
167
+
136
168
if (n >= until )
137
- return ;
169
+ return set_size (pids );
170
+
171
+ if (date_log_child > 0 )
172
+ timespec_store (& ts , MIN (until - n , date_log_child - n ));
173
+ else
174
+ timespec_store (& ts , until - n );
138
175
139
- timespec_store (& ts , until - n );
140
176
k = sigtimedwait (mask , NULL , & ts );
141
177
if (k != SIGCHLD ) {
142
178
143
- if (k < 0 && errno != EAGAIN ) {
144
- log_error_errno (errno , "sigtimedwait() failed: %m" );
145
- return ;
146
- }
179
+ if (k < 0 && errno != EAGAIN )
180
+ return log_error_errno (errno , "sigtimedwait() failed: %m" );
147
181
148
182
if (k >= 0 )
149
183
log_warning ("sigtimedwait() returned unexpected signal." );
@@ -154,10 +188,14 @@ static void wait_for_children(Set *pids, sigset_t *mask, usec_t timeout) {
154
188
static int killall (int sig , Set * pids , bool send_sighup ) {
155
189
_cleanup_closedir_ DIR * dir = NULL ;
156
190
struct dirent * d ;
191
+ int n_killed = 0 ;
192
+
193
+ /* Send the specified signal to all remaining processes, if not excluded by ignore_proc().
194
+ * Returns the number of processes to which the specified signal was sent */
157
195
158
196
dir = opendir ("/proc" );
159
197
if (!dir )
160
- return - errno ;
198
+ return log_warning_errno ( errno , "opendir(/proc) failed: %m" ) ;
161
199
162
200
FOREACH_DIRENT_ALL (d , dir , break ) {
163
201
pid_t pid ;
@@ -180,6 +218,7 @@ static int killall(int sig, Set *pids, bool send_sighup) {
180
218
}
181
219
182
220
if (kill (pid , sig ) >= 0 ) {
221
+ n_killed ++ ;
183
222
if (pids ) {
184
223
r = set_put (pids , PID_TO_PTR (pid ));
185
224
if (r < 0 )
@@ -205,13 +244,20 @@ static int killall(int sig, Set *pids, bool send_sighup) {
205
244
}
206
245
}
207
246
208
- return set_size ( pids ) ;
247
+ return n_killed ;
209
248
}
210
249
211
- void broadcast_signal (int sig , bool wait_for_exit , bool send_sighup , usec_t timeout ) {
250
+ int broadcast_signal (int sig , bool wait_for_exit , bool send_sighup , usec_t timeout ) {
251
+ int n_children_left ;
212
252
sigset_t mask , oldmask ;
213
253
_cleanup_set_free_ Set * pids = NULL ;
214
254
255
+ /* Send the specified signal to all remaining processes, if not excluded by ignore_proc().
256
+ * Return:
257
+ * - The number of processes still "alive" after the timeout (that should have been killed)
258
+ * if the function needs to wait for the end of the processes (wait_for_exit).
259
+ * - Otherwise, the number of processes to which the specified signal was sent */
260
+
215
261
if (wait_for_exit )
216
262
pids = set_new (NULL );
217
263
@@ -222,13 +268,15 @@ void broadcast_signal(int sig, bool wait_for_exit, bool send_sighup, usec_t time
222
268
if (kill (-1 , SIGSTOP ) < 0 && errno != ESRCH )
223
269
log_warning_errno (errno , "kill(-1, SIGSTOP) failed: %m" );
224
270
225
- killall (sig , pids , send_sighup );
271
+ n_children_left = killall (sig , pids , send_sighup );
226
272
227
273
if (kill (-1 , SIGCONT ) < 0 && errno != ESRCH )
228
274
log_warning_errno (errno , "kill(-1, SIGCONT) failed: %m" );
229
275
230
- if (wait_for_exit )
231
- wait_for_children (pids , & mask , timeout );
276
+ if (wait_for_exit && n_children_left > 0 )
277
+ n_children_left = wait_for_children (pids , & mask , timeout );
232
278
233
279
assert_se (sigprocmask (SIG_SETMASK , & oldmask , NULL ) == 0 );
280
+
281
+ return n_children_left ;
234
282
}
0 commit comments