]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/killall.c
Merge pull request #17732 from yuwata/core-use-synthetic_errno
[thirdparty/systemd.git] / src / core / killall.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
bd3fa1d2 2/***
96b2fb93 3 Copyright © 2010 ProFUSION embedded systems
bd3fa1d2
LP
4***/
5
bd3fa1d2 6#include <errno.h>
07630cea
LP
7#include <signal.h>
8#include <sys/wait.h>
aaf7eb81 9#include <unistd.h>
bd3fa1d2 10
b5efdb8a 11#include "alloc-util.h"
d4506129 12#include "def.h"
8fb3f009 13#include "dirent-util.h"
3ffd4af2 14#include "fd-util.h"
f97b34a6 15#include "format-util.h"
3ffd4af2 16#include "killall.h"
6bedfcbb 17#include "parse-util.h"
0b452006 18#include "process-util.h"
07630cea
LP
19#include "set.h"
20#include "string-util.h"
288a74cc 21#include "terminal-util.h"
07630cea 22#include "util.h"
bd3fa1d2 23
1359fffa 24static bool ignore_proc(pid_t pid, bool warn_rootfs) {
31885cd5 25 _cleanup_fclose_ FILE *f = NULL;
b68fa010 26 const char *p;
e45154c7 27 char c = 0;
bd3fa1d2
LP
28 uid_t uid;
29 int r;
30
31 /* We are PID 1, let's not commit suicide */
20ca2d10 32 if (pid <= 1)
bd3fa1d2
LP
33 return true;
34
e45154c7
LP
35 /* Ignore kernel threads */
36 r = is_kernel_thread(pid);
37 if (r != 0)
38 return true; /* also ignore processes where we can't determine this */
39
bd3fa1d2
LP
40 r = get_process_uid(pid, &uid);
41 if (r < 0)
42 return true; /* not really, but better safe than sorry */
43
44 /* Non-root processes otherwise are always subject to be killed */
45 if (uid != 0)
46 return false;
47
5841bd80
ZJS
48 p = procfs_file_alloca(pid, "cmdline");
49 f = fopen(p, "re");
bd3fa1d2
LP
50 if (!f)
51 return true; /* not really, but has the desired effect */
52
e45154c7
LP
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);
bd3fa1d2 57
9e615117 58 /* Processes with argv[0][0] = '@' we ignore from the killing spree.
bd3fa1d2 59 *
0bdd282a 60 * https://systemd.io/ROOT_STORAGE_DAEMONS */
9e615117
ZJS
61 if (c != '@')
62 return false;
63
64 if (warn_rootfs &&
65 pid_from_same_root_fs(pid) == 0) {
1359fffa 66
9e615117 67 _cleanup_free_ char *comm = NULL;
1359fffa 68
d3a94b3e 69 (void) get_process_comm(pid, &comm);
1359fffa 70
9e615117
ZJS
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));
75 }
bd3fa1d2 76
9e615117 77 return true;
bd3fa1d2
LP
78}
79
2c32f4f4 80static void log_children_no_yet_killed(Set *pids) {
2c32f4f4 81 _cleanup_free_ char *lst_child = NULL;
60cd3676 82 void *p;
2c32f4f4 83
90e74a66 84 SET_FOREACH(p, pids) {
2c32f4f4
BR
85 _cleanup_free_ char *s = NULL;
86
60cd3676
LP
87 if (get_process_comm(PTR_TO_PID(p), &s) < 0)
88 (void) asprintf(&s, PID_FMT, PTR_TO_PID(p));
89
90 if (!strextend(&lst_child, ", ", s, NULL)) {
91 log_oom();
92 return;
2c32f4f4
BR
93 }
94 }
95
60cd3676
LP
96 if (isempty(lst_child))
97 return;
98
99 log_warning("Waiting for process: %s", lst_child + 2);
2c32f4f4
BR
100}
101
a012f9f7 102static int wait_for_children(Set *pids, sigset_t *mask, usec_t timeout) {
60cd3676 103 usec_t until, date_log_child, n;
bd3fa1d2
LP
104
105 assert(mask);
106
a012f9f7
BR
107 /* Return the number of children remaining in the pids set: That correspond to the number
108 * of processes still "alive" after the timeout */
109
aaf7eb81 110 if (set_isempty(pids))
a012f9f7 111 return 0;
aaf7eb81 112
2c32f4f4
BR
113 n = now(CLOCK_MONOTONIC);
114 until = usec_add(n, timeout);
115 date_log_child = usec_add(n, 10u * USEC_PER_SEC);
116 if (date_log_child > until)
117 date_log_child = usec_add(n, timeout / 2u);
118
bd3fa1d2
LP
119 for (;;) {
120 struct timespec ts;
121 int k;
aaf7eb81 122 void *p;
bd3fa1d2 123
aaf7eb81
LP
124 /* First, let the kernel inform us about killed
125 * children. Most processes will probably be our
126 * children, but some are not (might be our
127 * grandchildren instead...). */
bd3fa1d2 128 for (;;) {
aaf7eb81 129 pid_t pid;
bd3fa1d2 130
aaf7eb81 131 pid = waitpid(-1, NULL, WNOHANG);
bd3fa1d2
LP
132 if (pid == 0)
133 break;
aaf7eb81
LP
134 if (pid < 0) {
135 if (errno == ECHILD)
136 break;
bd3fa1d2 137
a012f9f7 138 return log_error_errno(errno, "waitpid() failed: %m");
aaf7eb81
LP
139 }
140
fea72cc0 141 (void) set_remove(pids, PID_TO_PTR(pid));
aaf7eb81 142 }
bd3fa1d2 143
aaf7eb81
LP
144 /* Now explicitly check who might be remaining, who
145 * might not be our child. */
90e74a66 146 SET_FOREACH(p, pids) {
aaf7eb81 147
3448a969
AJ
148 /* kill(pid, 0) sends no signal, but it tells
149 * us whether the process still exists. */
150 if (kill(PTR_TO_PID(p), 0) == 0)
aaf7eb81
LP
151 continue;
152
153 if (errno != ESRCH)
154 continue;
155
156 set_remove(pids, p);
bd3fa1d2
LP
157 }
158
aaf7eb81 159 if (set_isempty(pids))
a012f9f7 160 return 0;
aaf7eb81 161
bd3fa1d2 162 n = now(CLOCK_MONOTONIC);
2c32f4f4
BR
163 if (date_log_child > 0 && n >= date_log_child) {
164 log_children_no_yet_killed(pids);
165 /* Log the children not yet killed only once */
166 date_log_child = 0;
167 }
168
bd3fa1d2 169 if (n >= until)
a012f9f7 170 return set_size(pids);
bd3fa1d2 171
2c32f4f4
BR
172 if (date_log_child > 0)
173 timespec_store(&ts, MIN(until - n, date_log_child - n));
174 else
175 timespec_store(&ts, until - n);
176
aaf7eb81
LP
177 k = sigtimedwait(mask, NULL, &ts);
178 if (k != SIGCHLD) {
bd3fa1d2 179
a012f9f7
BR
180 if (k < 0 && errno != EAGAIN)
181 return log_error_errno(errno, "sigtimedwait() failed: %m");
bd3fa1d2
LP
182
183 if (k >= 0)
184 log_warning("sigtimedwait() returned unexpected signal.");
185 }
186 }
187}
188
0bee65f0 189static int killall(int sig, Set *pids, bool send_sighup) {
aaf7eb81 190 _cleanup_closedir_ DIR *dir = NULL;
bd3fa1d2 191 struct dirent *d;
a012f9f7
BR
192 int n_killed = 0;
193
194 /* Send the specified signal to all remaining processes, if not excluded by ignore_proc().
195 * Returns the number of processes to which the specified signal was sent */
bd3fa1d2
LP
196
197 dir = opendir("/proc");
198 if (!dir)
a012f9f7 199 return log_warning_errno(errno, "opendir(/proc) failed: %m");
bd3fa1d2 200
8fb3f009 201 FOREACH_DIRENT_ALL(d, dir, break) {
bd3fa1d2 202 pid_t pid;
60053efb 203 int r;
bd3fa1d2 204
ec2ce0c5 205 if (!IN_SET(d->d_type, DT_DIR, DT_UNKNOWN))
bd3fa1d2
LP
206 continue;
207
208 if (parse_pid(d->d_name, &pid) < 0)
209 continue;
210
1359fffa 211 if (ignore_proc(pid, sig == SIGKILL && !in_initrd()))
bd3fa1d2
LP
212 continue;
213
df758e98 214 if (sig == SIGKILL) {
3e09eb5c 215 _cleanup_free_ char *s = NULL;
df758e98 216
74d6421d 217 (void) get_process_comm(pid, &s);
ccd06097 218 log_notice("Sending SIGKILL to PID "PID_FMT" (%s).", pid, strna(s));
df758e98
KS
219 }
220
aaf7eb81 221 if (kill(pid, sig) >= 0) {
a012f9f7 222 n_killed++;
60053efb 223 if (pids) {
fea72cc0 224 r = set_put(pids, PID_TO_PTR(pid));
60053efb
TA
225 if (r < 0)
226 log_oom();
227 }
aaf7eb81 228 } else if (errno != ENOENT)
56f64d95 229 log_warning_errno(errno, "Could not kill %d: %m", pid);
0bee65f0
LP
230
231 if (send_sighup) {
232 /* Optionally, also send a SIGHUP signal, but
233 only if the process has a controlling
234 tty. This is useful to allow handling of
235 shells which ignore SIGTERM but react to
236 SIGHUP. We do not send this to processes that
237 have no controlling TTY since we don't want to
238 trigger reloads of daemon processes. Also we
239 make sure to only send this after SIGTERM so
240 that SIGTERM is always first in the queue. */
241
0bee65f0 242 if (get_ctty_devnr(pid, NULL) >= 0)
5c5d9f26
ZJS
243 /* it's OK if the process is gone, just ignore the result */
244 (void) kill(pid, SIGHUP);
0bee65f0 245 }
bd3fa1d2
LP
246 }
247
a012f9f7 248 return n_killed;
bd3fa1d2
LP
249}
250
a012f9f7
BR
251int broadcast_signal(int sig, bool wait_for_exit, bool send_sighup, usec_t timeout) {
252 int n_children_left;
bd3fa1d2 253 sigset_t mask, oldmask;
e1d75803 254 _cleanup_set_free_ Set *pids = NULL;
aaf7eb81 255
763e7b5d
BR
256 /* Send the specified signal to all remaining processes, if not excluded by ignore_proc().
257 * Return:
258 * - The number of processes still "alive" after the timeout (that should have been killed)
259 * if the function needs to wait for the end of the processes (wait_for_exit).
260 * - Otherwise, the number of processes to which the specified signal was sent */
261
aaf7eb81 262 if (wait_for_exit)
d5099efc 263 pids = set_new(NULL);
bd3fa1d2
LP
264
265 assert_se(sigemptyset(&mask) == 0);
266 assert_se(sigaddset(&mask, SIGCHLD) == 0);
267 assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) == 0);
268
269 if (kill(-1, SIGSTOP) < 0 && errno != ESRCH)
56f64d95 270 log_warning_errno(errno, "kill(-1, SIGSTOP) failed: %m");
bd3fa1d2 271
a012f9f7 272 n_children_left = killall(sig, pids, send_sighup);
bd3fa1d2
LP
273
274 if (kill(-1, SIGCONT) < 0 && errno != ESRCH)
56f64d95 275 log_warning_errno(errno, "kill(-1, SIGCONT) failed: %m");
bd3fa1d2 276
a012f9f7
BR
277 if (wait_for_exit && n_children_left > 0)
278 n_children_left = wait_for_children(pids, &mask, timeout);
aaf7eb81
LP
279
280 assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) == 0);
a012f9f7
BR
281
282 return n_children_left;
bd3fa1d2 283}