From: Lennart Poettering Date: Thu, 17 Jun 2010 21:22:56 +0000 (+0200) Subject: manager: expose a few special units via SIGRTMIN+x signals X-Git-Tag: v1~173 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=7d7936059fac45b909faeb6a65dd7346e9d55378 manager: expose a few special units via SIGRTMIN+x signals --- diff --git a/fixme b/fixme index db3dda8b2..055fac488 100644 --- a/fixme +++ b/fixme @@ -71,6 +71,8 @@ * __attribute__ for sd_notifyf +* convenience library + Regularly: * look for close() vs. close_nointr() vs. close_nointr_nofail() diff --git a/src/manager.c b/src/manager.c index 385b371db..2ad60721a 100644 --- a/src/manager.c +++ b/src/manager.c @@ -157,14 +157,23 @@ static int manager_setup_signals(Manager *m) { assert_se(sigaction(SIGCHLD, &sa, NULL) == 0); assert_se(sigemptyset(&mask) == 0); - assert_se(sigaddset(&mask, SIGCHLD) == 0); - assert_se(sigaddset(&mask, SIGTERM) == 0); - assert_se(sigaddset(&mask, SIGHUP) == 0); - assert_se(sigaddset(&mask, SIGUSR1) == 0); - assert_se(sigaddset(&mask, SIGUSR2) == 0); - assert_se(sigaddset(&mask, SIGINT) == 0); /* Kernel sends us this on control-alt-del */ - assert_se(sigaddset(&mask, SIGWINCH) == 0); /* Kernel sends us this on kbrequest (alt-arrowup) */ - assert_se(sigaddset(&mask, SIGPWR) == 0); /* Some kernel drivers and upsd send us this on power failure */ + + sigset_add_many(&mask, + SIGCHLD, /* Child died */ + SIGTERM, /* Reexecute daemon */ + SIGHUP, /* Reload configuration */ + SIGUSR1, /* systemd/upstart: reconnect to D-Bus */ + SIGUSR2, /* systemd: dump status */ + SIGINT, /* Kernel sends us this on control-alt-del */ + SIGWINCH, /* Kernel sends us this on kbrequest (alt-arrowup) */ + SIGPWR, /* Some kernel drivers and upsd send us this on power failure */ + SIGRTMIN+0, /* systemd: start default.target */ + SIGRTMIN+1, /* systemd: start rescue.target */ + SIGRTMIN+2, /* systemd: isolate emergency.target */ + SIGRTMIN+3, /* systemd: start halt.target */ + SIGRTMIN+4, /* systemd: start poweroff.target */ + SIGRTMIN+5, /* systemd: start reboot.target */ + -1); assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0); m->signal_watch.type = WATCH_SIGNAL; @@ -1731,10 +1740,10 @@ static int manager_dispatch_sigchld(Manager *m) { return 0; } -static int manager_start_target(Manager *m, const char *name) { +static int manager_start_target(Manager *m, const char *name, JobMode mode) { int r; - if ((r = manager_add_job_by_name(m, JOB_START, name, JOB_REPLACE, true, NULL)) < 0) + if ((r = manager_add_job_by_name(m, JOB_START, name, mode, true, NULL)) < 0) log_error("Failed to enqueue %s job: %s", name, strerror(-r)); return r; @@ -1777,12 +1786,12 @@ static int manager_process_signal_fd(Manager *m) { case SIGINT: if (m->running_as == MANAGER_INIT) { - manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET); + manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE); break; } /* Run the exit target if there is one, if not, just exit. */ - if (manager_start_target(m, SPECIAL_EXIT_SERVICE) < 0) { + if (manager_start_target(m, SPECIAL_EXIT_SERVICE, JOB_REPLACE) < 0) { m->exit_code = MANAGER_EXIT; return 0; } @@ -1791,14 +1800,14 @@ static int manager_process_signal_fd(Manager *m) { case SIGWINCH: if (m->running_as == MANAGER_INIT) - manager_start_target(m, SPECIAL_KBREQUEST_TARGET); + manager_start_target(m, SPECIAL_KBREQUEST_TARGET, JOB_REPLACE); /* This is a nop on non-init */ break; case SIGPWR: if (m->running_as == MANAGER_INIT) - manager_start_target(m, SPECIAL_SIGPWR_TARGET); + manager_start_target(m, SPECIAL_SIGPWR_TARGET, JOB_REPLACE); /* This is a nop on non-init */ break; @@ -1816,7 +1825,7 @@ static int manager_process_signal_fd(Manager *m) { if (!u || !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u))) { log_info("Loading D-Bus service..."); - manager_start_target(m, SPECIAL_DBUS_SERVICE); + manager_start_target(m, SPECIAL_DBUS_SERVICE, JOB_REPLACE); } break; @@ -1853,9 +1862,26 @@ static int manager_process_signal_fd(Manager *m) { m->exit_code = MANAGER_RELOAD; break; - default: + default: { + static const char * const table[] = { + [0] = SPECIAL_DEFAULT_TARGET, + [1] = SPECIAL_RESCUE_TARGET, + [2] = SPECIAL_EMERGENCY_SERVICE, + [3] = SPECIAL_HALT_TARGET, + [4] = SPECIAL_POWEROFF_TARGET, + [5] = SPECIAL_REBOOT_TARGET + }; + + if ((int) sfsi.ssi_signo >= SIGRTMIN+0 && + (int) sfsi.ssi_signo < SIGRTMIN+(int) ELEMENTSOF(table)) { + manager_start_target(m, table[sfsi.ssi_signo - SIGRTMIN], + sfsi.ssi_signo == 2 ? JOB_ISOLATE : JOB_REPLACE); + break; + } + log_info("Got unhandled signal <%s>.", strsignal(sfsi.ssi_signo)); } + } } if (sigchld) diff --git a/src/manager.h b/src/manager.h index 070a27f70..5ee75d524 100644 --- a/src/manager.h +++ b/src/manager.h @@ -113,6 +113,10 @@ struct Watch { #define SPECIAL_SYSINIT_TARGET "sysinit.target" #define SPECIAL_RESCUE_TARGET "rescue.target" #define SPECIAL_EXIT_SERVICE "exit.service" +#define SPECIAL_EMERGENCY_SERVICE "emergency.service" +#define SPECIAL_HALT_TARGET "halt.target" +#define SPECIAL_POWEROFF_TARGET "poweroff.target" +#define SPECIAL_REBOOT_TARGET "reboot.target" #ifndef SPECIAL_DBUS_SERVICE #define SPECIAL_DBUS_SERVICE "dbus.service" diff --git a/src/util.c b/src/util.c index 8f70c0f28..4fdc8e57c 100644 --- a/src/util.c +++ b/src/util.c @@ -2205,6 +2205,18 @@ void rename_process(const char name[8]) { strncpy(program_invocation_name, name, strlen(program_invocation_name)); } +void sigset_add_many(sigset_t *ss, ...) { + va_list ap; + int sig; + + assert(ss); + + va_start(ap, ss); + while ((sig = va_arg(ap, int)) > 0) + assert_se(sigaddset(ss, sig) == 0); + va_end(ap); +} + static const char *const ioprio_class_table[] = { [IOPRIO_CLASS_NONE] = "none", [IOPRIO_CLASS_RT] = "realtime", diff --git a/src/util.h b/src/util.h index 1ca8f90cf..f3aec1d43 100644 --- a/src/util.h +++ b/src/util.h @@ -256,6 +256,8 @@ int dir_is_empty(const char *path); void rename_process(const char name[8]); +void sigset_add_many(sigset_t *ss, ...); + const char *ioprio_class_to_string(int i); int ioprio_class_from_string(const char *s);