]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/killall.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright © 2010 ProFUSION embedded systems
11 #include "alloc-util.h"
13 #include "dirent-util.h"
15 #include "format-util.h"
17 #include "parse-util.h"
18 #include "process-util.h"
20 #include "string-util.h"
21 #include "terminal-util.h"
24 static bool ignore_proc(pid_t pid
, bool warn_rootfs
) {
25 _cleanup_fclose_
FILE *f
= NULL
;
31 /* We are PID 1, let's not commit suicide */
35 /* Ignore kernel threads */
36 r
= is_kernel_thread(pid
);
38 return true; /* also ignore processes where we can't determine this */
40 r
= get_process_uid(pid
, &uid
);
42 return true; /* not really, but better safe than sorry */
44 /* Non-root processes otherwise are always subject to be killed */
48 p
= procfs_file_alloca(pid
, "cmdline");
51 return true; /* not really, but has the desired effect */
53 /* Try to read the first character of the command line. If the cmdline is empty (which might be the case for
54 * kernel threads but potentially also other stuff), this line won't do anything, but we don't care much, as
55 * actual kernel threads are already filtered out above. */
56 (void) fread(&c
, 1, 1, f
);
58 /* Processes with argv[0][0] = '@' we ignore from the killing spree.
60 * http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons */
65 pid_from_same_root_fs(pid
) == 0) {
67 _cleanup_free_
char *comm
= NULL
;
69 (void) get_process_comm(pid
, &comm
);
71 log_notice("Process " PID_FMT
" (%s) has been marked to be excluded from killing. It is "
72 "running from the root file system, and thus likely to block re-mounting of the "
73 "root file system to read-only. Please consider moving it into an initrd file "
74 "system instead.", pid
, strna(comm
));
80 static void log_children_no_yet_killed(Set
*pids
) {
83 _cleanup_free_
char *lst_child
= NULL
;
85 SET_FOREACH(p
, pids
, i
) {
86 _cleanup_free_
char *s
= NULL
;
88 if (get_process_comm(PTR_TO_PID(p
), &s
) == 0) {
89 if (!strextend(&lst_child
, ", ", s
, NULL
))
94 if (!isempty(lst_child
))
95 log_notice("Waiting for process:%s", lst_child
+ 1);
98 static int wait_for_children(Set
*pids
, sigset_t
*mask
, usec_t timeout
) {
100 usec_t date_log_child
;
105 /* Return the number of children remaining in the pids set: That correspond to the number
106 * of processes still "alive" after the timeout */
108 if (set_isempty(pids
))
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);
123 /* First, let the kernel inform us about killed
124 * children. Most processes will probably be our
125 * children, but some are not (might be our
126 * grandchildren instead...). */
130 pid
= waitpid(-1, NULL
, WNOHANG
);
137 return log_error_errno(errno
, "waitpid() failed: %m");
140 (void) set_remove(pids
, PID_TO_PTR(pid
));
143 /* Now explicitly check who might be remaining, who
144 * might not be our child. */
145 SET_FOREACH(p
, pids
, i
) {
147 /* kill(pid, 0) sends no signal, but it tells
148 * us whether the process still exists. */
149 if (kill(PTR_TO_PID(p
), 0) == 0)
158 if (set_isempty(pids
))
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 */
169 return set_size(pids
);
171 if (date_log_child
> 0)
172 timespec_store(&ts
, MIN(until
- n
, date_log_child
- n
));
174 timespec_store(&ts
, until
- n
);
176 k
= sigtimedwait(mask
, NULL
, &ts
);
179 if (k
< 0 && errno
!= EAGAIN
)
180 return log_error_errno(errno
, "sigtimedwait() failed: %m");
183 log_warning("sigtimedwait() returned unexpected signal.");
188 static int killall(int sig
, Set
*pids
, bool send_sighup
) {
189 _cleanup_closedir_
DIR *dir
= NULL
;
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 */
196 dir
= opendir("/proc");
198 return log_warning_errno(errno
, "opendir(/proc) failed: %m");
200 FOREACH_DIRENT_ALL(d
, dir
, break) {
204 if (!IN_SET(d
->d_type
, DT_DIR
, DT_UNKNOWN
))
207 if (parse_pid(d
->d_name
, &pid
) < 0)
210 if (ignore_proc(pid
, sig
== SIGKILL
&& !in_initrd()))
213 if (sig
== SIGKILL
) {
214 _cleanup_free_
char *s
= NULL
;
216 get_process_comm(pid
, &s
);
217 log_notice("Sending SIGKILL to PID "PID_FMT
" (%s).", pid
, strna(s
));
220 if (kill(pid
, sig
) >= 0) {
223 r
= set_put(pids
, PID_TO_PTR(pid
));
227 } else if (errno
!= ENOENT
)
228 log_warning_errno(errno
, "Could not kill %d: %m", pid
);
231 /* Optionally, also send a SIGHUP signal, but
232 only if the process has a controlling
233 tty. This is useful to allow handling of
234 shells which ignore SIGTERM but react to
235 SIGHUP. We do not send this to processes that
236 have no controlling TTY since we don't want to
237 trigger reloads of daemon processes. Also we
238 make sure to only send this after SIGTERM so
239 that SIGTERM is always first in the queue. */
241 if (get_ctty_devnr(pid
, NULL
) >= 0)
242 /* it's OK if the process is gone, just ignore the result */
243 (void) kill(pid
, SIGHUP
);
250 int broadcast_signal(int sig
, bool wait_for_exit
, bool send_sighup
, usec_t timeout
) {
252 sigset_t mask
, oldmask
;
253 _cleanup_set_free_ Set
*pids
= NULL
;
255 /* Send the specified signal to all remaining processes, if not excluded by ignore_proc().
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 */
262 pids
= set_new(NULL
);
264 assert_se(sigemptyset(&mask
) == 0);
265 assert_se(sigaddset(&mask
, SIGCHLD
) == 0);
266 assert_se(sigprocmask(SIG_BLOCK
, &mask
, &oldmask
) == 0);
268 if (kill(-1, SIGSTOP
) < 0 && errno
!= ESRCH
)
269 log_warning_errno(errno
, "kill(-1, SIGSTOP) failed: %m");
271 n_children_left
= killall(sig
, pids
, send_sighup
);
273 if (kill(-1, SIGCONT
) < 0 && errno
!= ESRCH
)
274 log_warning_errno(errno
, "kill(-1, SIGCONT) failed: %m");
276 if (wait_for_exit
&& n_children_left
> 0)
277 n_children_left
= wait_for_children(pids
, &mask
, timeout
);
279 assert_se(sigprocmask(SIG_SETMASK
, &oldmask
, NULL
) == 0);
281 return n_children_left
;