]>
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
;
32 /* We are PID 1, let's not commit suicide */
36 r
= get_process_uid(pid
, &uid
);
38 return true; /* not really, but better safe than sorry */
40 /* Non-root processes otherwise are always subject to be killed */
44 p
= procfs_file_alloca(pid
, "cmdline");
47 return true; /* not really, but has the desired effect */
49 count
= fread(&c
, 1, 1, f
);
51 /* Kernel threads have an empty cmdline */
55 /* Processes with argv[0][0] = '@' we ignore from the killing spree.
57 * http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons */
62 pid_from_same_root_fs(pid
) == 0) {
64 _cleanup_free_
char *comm
= NULL
;
66 get_process_comm(pid
, &comm
);
68 log_notice("Process " PID_FMT
" (%s) has been marked to be excluded from killing. It is "
69 "running from the root file system, and thus likely to block re-mounting of the "
70 "root file system to read-only. Please consider moving it into an initrd file "
71 "system instead.", pid
, strna(comm
));
77 static void wait_for_children(Set
*pids
, sigset_t
*mask
, usec_t timeout
) {
82 if (set_isempty(pids
))
85 until
= now(CLOCK_MONOTONIC
) + timeout
;
93 /* First, let the kernel inform us about killed
94 * children. Most processes will probably be our
95 * children, but some are not (might be our
96 * grandchildren instead...). */
100 pid
= waitpid(-1, NULL
, WNOHANG
);
107 log_error_errno(errno
, "waitpid() failed: %m");
111 (void) set_remove(pids
, PID_TO_PTR(pid
));
114 /* Now explicitly check who might be remaining, who
115 * might not be our child. */
116 SET_FOREACH(p
, pids
, i
) {
118 /* kill(pid, 0) sends no signal, but it tells
119 * us whether the process still exists. */
120 if (kill(PTR_TO_PID(p
), 0) == 0)
129 if (set_isempty(pids
))
132 n
= now(CLOCK_MONOTONIC
);
136 timespec_store(&ts
, until
- n
);
137 k
= sigtimedwait(mask
, NULL
, &ts
);
140 if (k
< 0 && errno
!= EAGAIN
) {
141 log_error_errno(errno
, "sigtimedwait() failed: %m");
146 log_warning("sigtimedwait() returned unexpected signal.");
151 static int killall(int sig
, Set
*pids
, bool send_sighup
) {
152 _cleanup_closedir_
DIR *dir
= NULL
;
155 dir
= opendir("/proc");
159 FOREACH_DIRENT_ALL(d
, dir
, break) {
163 if (!IN_SET(d
->d_type
, DT_DIR
, DT_UNKNOWN
))
166 if (parse_pid(d
->d_name
, &pid
) < 0)
169 if (ignore_proc(pid
, sig
== SIGKILL
&& !in_initrd()))
172 if (sig
== SIGKILL
) {
173 _cleanup_free_
char *s
= NULL
;
175 get_process_comm(pid
, &s
);
176 log_notice("Sending SIGKILL to PID "PID_FMT
" (%s).", pid
, strna(s
));
179 if (kill(pid
, sig
) >= 0) {
181 r
= set_put(pids
, PID_TO_PTR(pid
));
185 } else if (errno
!= ENOENT
)
186 log_warning_errno(errno
, "Could not kill %d: %m", pid
);
189 /* Optionally, also send a SIGHUP signal, but
190 only if the process has a controlling
191 tty. This is useful to allow handling of
192 shells which ignore SIGTERM but react to
193 SIGHUP. We do not send this to processes that
194 have no controlling TTY since we don't want to
195 trigger reloads of daemon processes. Also we
196 make sure to only send this after SIGTERM so
197 that SIGTERM is always first in the queue. */
199 if (get_ctty_devnr(pid
, NULL
) >= 0)
200 /* it's OK if the process is gone, just ignore the result */
201 (void) kill(pid
, SIGHUP
);
205 return set_size(pids
);
208 void broadcast_signal(int sig
, bool wait_for_exit
, bool send_sighup
, usec_t timeout
) {
209 sigset_t mask
, oldmask
;
210 _cleanup_set_free_ Set
*pids
= NULL
;
213 pids
= set_new(NULL
);
215 assert_se(sigemptyset(&mask
) == 0);
216 assert_se(sigaddset(&mask
, SIGCHLD
) == 0);
217 assert_se(sigprocmask(SIG_BLOCK
, &mask
, &oldmask
) == 0);
219 if (kill(-1, SIGSTOP
) < 0 && errno
!= ESRCH
)
220 log_warning_errno(errno
, "kill(-1, SIGSTOP) failed: %m");
222 killall(sig
, pids
, send_sighup
);
224 if (kill(-1, SIGCONT
) < 0 && errno
!= ESRCH
)
225 log_warning_errno(errno
, "kill(-1, SIGCONT) failed: %m");
228 wait_for_children(pids
, &mask
, timeout
);
230 assert_se(sigprocmask(SIG_SETMASK
, &oldmask
, NULL
) == 0);