killall.c revision ccd06097c79218f7d5ea4c21721bbcbc7c467dca
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering/***
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering This file is part of systemd.
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering Copyright 2010 ProFUSION embedded systems
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering systemd is free software; you can redistribute it and/or modify it
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering under the terms of the GNU Lesser General Public License as published by
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering (at your option) any later version.
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering systemd is distributed in the hope that it will be useful, but
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering Lesser General Public License for more details.
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering You should have received a copy of the GNU Lesser General Public License
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering***/
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include <sys/wait.h>
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include <signal.h>
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include <errno.h>
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include <unistd.h>
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "util.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "def.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "killall.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "set.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#define TIMEOUT_USEC (10 * USEC_PER_SEC)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic bool ignore_proc(pid_t pid) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering char c, *p;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering size_t count;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering uid_t uid;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering int r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* We are PID 1, let's not commit suicide */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (pid == 1)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return true;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = get_process_uid(pid, &uid);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return true; /* not really, but better safe than sorry */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* Non-root processes otherwise are always subject to be killed */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (uid != 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return false;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering p = procfs_file_alloca(pid, "cmdline");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering f = fopen(p, "re");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!f)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return true; /* not really, but has the desired effect */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering count = fread(&c, 1, 1, f);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* Kernel threads have an empty cmdline */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (count <= 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return true;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* Processes with argv[0][0] = '@' we ignore from the killing
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering * spree.
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering *
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering * http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (count == 1 && c == '@')
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return true;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return false;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic void wait_for_children(Set *pids, sigset_t *mask) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering usec_t until;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(mask);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (set_isempty(pids))
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering until = now(CLOCK_MONOTONIC) + TIMEOUT_USEC;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering for (;;) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering struct timespec ts;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering int k;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering usec_t n;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering void *p;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering Iterator i;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* First, let the kernel inform us about killed
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering * children. Most processes will probably be our
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering * children, but some are not (might be our
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering * grandchildren instead...). */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering for (;;) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering pid_t pid;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering pid = waitpid(-1, NULL, WNOHANG);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (pid == 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering break;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (pid < 0) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (errno == ECHILD)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering break;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_error("waitpid() failed: %m");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering set_remove(pids, ULONG_TO_PTR(pid));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* Now explicitly check who might be remaining, who
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering * might not be our child. */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering SET_FOREACH(p, pids, i) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* We misuse getpgid as a check whether a
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering * process still exists. */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (getpgid((pid_t) PTR_TO_ULONG(p)) >= 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering continue;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (errno != ESRCH)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering continue;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering set_remove(pids, p);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (set_isempty(pids))
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering n = now(CLOCK_MONOTONIC);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (n >= until)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering timespec_store(&ts, until - n);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering k = sigtimedwait(mask, NULL, &ts);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (k != SIGCHLD) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (k < 0 && errno != EAGAIN) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_error("sigtimedwait() failed: %m");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (k >= 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_warning("sigtimedwait() returned unexpected signal.");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic int killall(int sig, Set *pids, bool send_sighup) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering _cleanup_closedir_ DIR *dir = NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering struct dirent *d;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering dir = opendir("/proc");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!dir)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -errno;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering while ((d = readdir(dir))) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering pid_t pid;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (d->d_type != DT_DIR &&
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering d->d_type != DT_UNKNOWN)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering continue;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (parse_pid(d->d_name, &pid) < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering continue;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (ignore_proc(pid))
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering continue;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (sig == SIGKILL) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering _cleanup_free_ char *s;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering get_process_comm(pid, &s);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_notice("Sending SIGKILL to PID "PID_FMT" (%s).", pid, strna(s));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (kill(pid, sig) >= 0) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (pids)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering set_put(pids, ULONG_TO_PTR(pid));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering } else if (errno != ENOENT)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_warning("Could not kill %d: %m", pid);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (send_sighup) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* Optionally, also send a SIGHUP signal, but
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering only if the process has a controlling
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering tty. This is useful to allow handling of
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering shells which ignore SIGTERM but react to
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering SIGHUP. We do not send this to processes that
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering have no controlling TTY since we don't want to
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering trigger reloads of daemon processes. Also we
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering make sure to only send this after SIGTERM so
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering that SIGTERM is always first in the queue. */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (get_ctty_devnr(pid, NULL) >= 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering kill(pid, SIGHUP);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return set_size(pids);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringvoid broadcast_signal(int sig, bool wait_for_exit, bool send_sighup) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering sigset_t mask, oldmask;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering Set *pids = NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (wait_for_exit)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering pids = set_new(trivial_hash_func, trivial_compare_func);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert_se(sigemptyset(&mask) == 0);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert_se(sigaddset(&mask, SIGCHLD) == 0);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) == 0);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (kill(-1, SIGSTOP) < 0 && errno != ESRCH)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_warning("kill(-1, SIGSTOP) failed: %m");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering killall(sig, pids, send_sighup);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (kill(-1, SIGCONT) < 0 && errno != ESRCH)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_warning("kill(-1, SIGCONT) failed: %m");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (wait_for_exit)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering wait_for_children(pids, &mask);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) == 0);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering set_free(pids);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering