1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 ProFUSION embedded systems
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
32 #define TIMEOUT_USEC (10 * USEC_PER_SEC)
34 static bool ignore_proc(pid_t pid) {
42 /* We are PID 1, let's not commit suicide */
46 r = get_process_uid(pid, &uid);
48 return true; /* not really, but better safe than sorry */
50 /* Non-root processes otherwise are always subject to be killed */
54 snprintf(buf, sizeof(buf), "/proc/%lu/cmdline", (unsigned long) pid);
59 return true; /* not really, but has the desired effect */
61 count = fread(&c, 1, 1, f);
64 /* Kernel threads have an empty cmdline */
68 /* Processes with argv[0][0] = '@' we ignore from the killing
71 * http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons */
72 if (count == 1 && c == '@')
78 static void wait_for_children(Set *pids, sigset_t *mask) {
83 if (set_isempty(pids))
86 until = now(CLOCK_MONOTONIC) + TIMEOUT_USEC;
94 /* First, let the kernel inform us about killed
95 * children. Most processes will probably be our
96 * children, but some are not (might be our
97 * grandchildren instead...). */
101 pid = waitpid(-1, NULL, WNOHANG);
108 log_error("waitpid() failed: %m");
112 set_remove(pids, ULONG_TO_PTR(pid));
115 /* Now explicitly check who might be remaining, who
116 * might not be our child. */
117 SET_FOREACH(p, pids, i) {
119 /* We misuse getpgid as a check whether a
120 * process still exists. */
121 if (getpgid((pid_t) PTR_TO_ULONG(p)) >= 0)
130 if (set_isempty(pids))
133 n = now(CLOCK_MONOTONIC);
137 timespec_store(&ts, until - n);
138 k = sigtimedwait(mask, NULL, &ts);
141 if (k < 0 && errno != EAGAIN) {
142 log_error("sigtimedwait() failed: %m");
147 log_warning("sigtimedwait() returned unexpected signal.");
152 static int killall(int sig, Set *pids) {
153 _cleanup_closedir_ DIR *dir = NULL;
156 dir = opendir("/proc");
160 while ((d = readdir(dir))) {
163 if (d->d_type != DT_DIR &&
164 d->d_type != DT_UNKNOWN)
167 if (parse_pid(d->d_name, &pid) < 0)
170 if (ignore_proc(pid))
173 if (sig == SIGKILL) {
174 _cleanup_free_ char *s;
176 get_process_comm(pid, &s);
177 log_notice("Sending SIGKILL to PID %lu (%s).", (unsigned long) pid, strna(s));
180 if (kill(pid, sig) >= 0) {
182 set_put(pids, ULONG_TO_PTR((unsigned long) pid));
183 } else if (errno != ENOENT)
184 log_warning("Could not kill %d: %m", pid);
187 return set_size(pids);
190 void broadcast_signal(int sig, bool wait_for_exit) {
191 sigset_t mask, oldmask;
195 pids = set_new(trivial_hash_func, trivial_compare_func);
197 assert_se(sigemptyset(&mask) == 0);
198 assert_se(sigaddset(&mask, SIGCHLD) == 0);
199 assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) == 0);
201 if (kill(-1, SIGSTOP) < 0 && errno != ESRCH)
202 log_warning("kill(-1, SIGSTOP) failed: %m");
206 if (kill(-1, SIGCONT) < 0 && errno != ESRCH)
207 log_warning("kill(-1, SIGCONT) failed: %m");
210 wait_for_children(pids, &mask);
212 assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) == 0);