manager.c revision f0469b8c4abbeee9ca69678245cd08314adc24c0
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering This file is part of systemd.
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering Copyright 2010 Lennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering systemd is free software; you can redistribute it and/or modify it
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering under the terms of the GNU Lesser General Public License as published by
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering (at your option) any later version.
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering systemd is distributed in the hope that it will be useful, but
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering Lesser General Public License for more details.
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering You should have received a copy of the GNU Lesser General Public License
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering/* Initial delay and the interval for printing status messages about running jobs */
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering#define JOBS_IN_PROGRESS_WAIT_USEC (5*USEC_PER_SEC)
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering#define JOBS_IN_PROGRESS_PERIOD_USEC (USEC_PER_SEC / 3)
9ff09bcb86fb125768667aca9bc0b10b1745370aShawn Landdenstatic int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
9ff09bcb86fb125768667aca9bc0b10b1745370aShawn Landdenstatic int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
9ff09bcb86fb125768667aca9bc0b10b1745370aShawn Landdenstatic int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poetteringstatic int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
9ff09bcb86fb125768667aca9bc0b10b1745370aShawn Landdenstatic int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata);
9ff09bcb86fb125768667aca9bc0b10b1745370aShawn Landdenstatic int manager_dispatch_run_queue(sd_event_source *source, void *userdata);
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poetteringstatic void manager_undo_generators(Manager *m);
9ff09bcb86fb125768667aca9bc0b10b1745370aShawn Landdenstatic void manager_watch_jobs_in_progress(Manager *m) {
9ff09bcb86fb125768667aca9bc0b10b1745370aShawn Landden next = now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_WAIT_USEC;
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek manager_dispatch_jobs_in_progress, m);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering (void) sd_event_source_set_description(m->jobs_in_progress_event_source, "manager-jobs-in-progress");
2667cc25896a15f82f9f1583e80d416beb1316e1Thomas Hindoe Paaboel Andersen#define CYLON_BUFFER_EXTRA (2*(sizeof(ANSI_RED)-1) + sizeof(ANSI_HIGHLIGHT_RED)-1 + 2*(sizeof(ANSI_NORMAL)-1))
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poetteringstatic void draw_cylon(char buffer[], size_t buflen, unsigned width, unsigned pos) {
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering assert(buflen >= CYLON_BUFFER_EXTRA + width + 1);
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering assert(pos <= width+1); /* 0 or width+1 mean that the center light is behind the corner */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sieversvoid manager_flip_auto_status(Manager *m, bool enable) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers manager_set_show_status(m, SHOW_STATUS_TEMPORARY);
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersenstatic void manager_print_jobs_in_progress(Manager *m) {
adacb9575a09981fcf11279f2f661e3fc21e58ffLennart Poettering char time[FORMAT_TIMESPAN_MAX], limit[FORMAT_TIMESPAN_MAX] = "no limit";
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers print_nr = (m->jobs_in_progress_iteration / JOBS_IN_PROGRESS_PERIOD_DIVISOR) % m->n_running_jobs;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering if (j->state == JOB_RUNNING && counter++ == print_nr)
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen /* m->n_running_jobs must be consistent with the contents of m->jobs,
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering * so the above loop must have succeeded in finding j. */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering cylon_pos = m->jobs_in_progress_iteration % 14;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering draw_cylon(cylon, sizeof(cylon), 6, cylon_pos);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering if (asprintf(&job_of_n, "(%u of %u) ", counter, m->n_running_jobs) < 0)
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen format_timespan(time, sizeof(time), now(CLOCK_MONOTONIC) - j->begin_usec, 1*USEC_PER_SEC);
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen if (job_get_timeout(j, &x) > 0)
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen format_timespan(limit, sizeof(limit), x - j->begin_usec, 1*USEC_PER_SEC);
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen manager_status_printf(m, STATUS_TYPE_EPHEMERAL, cylon,
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen "%sA %s job is running for %s (%s / %s)",
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersenstatic int have_ask_password(void) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering dir = opendir("/run/systemd/ask-password");
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poetteringstatic int manager_dispatch_ask_password_fd(sd_event_source *source,
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering int fd, uint32_t revents, void *userdata) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering m->have_ask_password = have_ask_password();
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* Log error but continue. Negative have_ask_password
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering * is treated as unknown status. */
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen log_error_errno(m->have_ask_password, "Failed to list /run/systemd/ask-password: %m");
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersenstatic void manager_close_ask_password(Manager *m) {
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen m->ask_password_event_source = sd_event_source_unref(m->ask_password_event_source);
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen m->ask_password_inotify_fd = safe_close(m->ask_password_inotify_fd);
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen m->have_ask_password = -EINVAL;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poetteringstatic int manager_check_ask_password(Manager *m) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering mkdir_p_label("/run/systemd/ask-password", 0755);
e5609878d8802e2469c433be418bcbcf55fbe63bLennart Poettering m->ask_password_inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering return log_error_errno(errno, "inotify_init1() failed: %m");
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering if (inotify_add_watch(m->ask_password_inotify_fd, "/run/systemd/ask-password", IN_CREATE|IN_DELETE|IN_MOVE) < 0) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering log_error_errno(errno, "Failed to add watch on /run/systemd/ask-password: %m");
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen manager_close_ask_password(m);
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen r = sd_event_add_io(m->event, &m->ask_password_event_source,
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen m->ask_password_inotify_fd, EPOLLIN,
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen manager_dispatch_ask_password_fd, m);
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen log_error_errno(errno, "Failed to add event source for /run/systemd/ask-password: %m");
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen manager_close_ask_password(m);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering (void) sd_event_source_set_description(m->ask_password_event_source, "manager-ask-password");
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* Queries might have been added meanwhile... */
7568345034f2890af745747783c5abfbf6eccf0fLennart Poettering manager_dispatch_ask_password_fd(m->ask_password_event_source,
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidtstatic int manager_watch_idle_pipe(Manager *m) {
07a062a79374406e8f6b5a1e2f80c80baf031567Jason St. John r = sd_event_add_io(m->event, &m->idle_pipe_event_source, m->idle_pipe[2], EPOLLIN, manager_dispatch_idle_pipe_fd, m);
4f8f66cb4236783cd3cbee97fefc9aaa8469ac08Zbigniew Jędrzejewski-Szmek return log_error_errno(r, "Failed to watch idle pipe: %m");
4f8f66cb4236783cd3cbee97fefc9aaa8469ac08Zbigniew Jędrzejewski-Szmek (void) sd_event_source_set_description(m->idle_pipe_event_source, "manager-idle-pipe");
4f8f66cb4236783cd3cbee97fefc9aaa8469ac08Zbigniew Jędrzejewski-Szmekstatic void manager_close_idle_pipe(Manager *m) {
4f8f66cb4236783cd3cbee97fefc9aaa8469ac08Zbigniew Jędrzejewski-Szmek m->idle_pipe_event_source = sd_event_source_unref(m->idle_pipe_event_source);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poetteringstatic int manager_setup_time_change(Manager *m) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* We only care for the cancellation event, hence we set the
c978343015c787713651dff571acb5207367f5f2Lennart Poettering * timeout to the latest possible value. */
c978343015c787713651dff571acb5207367f5f2Lennart Poettering assert_cc(sizeof(time_t) == sizeof(TIME_T_MAX));
c978343015c787713651dff571acb5207367f5f2Lennart Poettering /* Uses TFD_TIMER_CANCEL_ON_SET to get notifications whenever
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering * CLOCK_REALTIME makes a jump relative to CLOCK_MONOTONIC */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering m->time_change_fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering return log_error_errno(errno, "Failed to create timerfd: %m");
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering if (timerfd_settime(m->time_change_fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering log_debug_errno(errno, "Failed to set up TFD_TIMER_CANCEL_ON_SET, ignoring: %m");
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek m->time_change_fd = safe_close(m->time_change_fd);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering r = sd_event_add_io(m->event, &m->time_change_event_source, m->time_change_fd, EPOLLIN, manager_dispatch_time_change_fd, m);
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek return log_error_errno(r, "Failed to create time change event source: %m");
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering (void) sd_event_source_set_description(m->time_change_event_source, "manager-time-change");
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering log_debug("Set up TFD_TIMER_CANCEL_ON_SET timerfd.");
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersenstatic int enable_special_signals(Manager *m) {
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen /* Enable that we get SIGINT on control-alt-del. In containers
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen * this will fail with EPERM (older) or EINVAL (newer), so
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen * ignore that. */
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen if (reboot(RB_DISABLE_CAD) < 0 && errno != EPERM && errno != EINVAL)
c978343015c787713651dff571acb5207367f5f2Lennart Poettering log_warning_errno(errno, "Failed to enable ctrl-alt-del handling: %m");
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* Support systems without virtual console */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering log_warning_errno(errno, "Failed to open /dev/tty0: %m");
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* Enable that we get SIGWINCH on kbrequest */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering if (ioctl(fd, KDSIGACCEPT, SIGWINCH) < 0)
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering log_warning_errno(errno, "Failed to enable kbrequest handling: %m");
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poetteringstatic int manager_setup_signals(Manager *m) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen /* We make liberal use of realtime signals here. On
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering * Linux/glibc we have 30 of them (with the exception of Linux
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering * on hppa, see below), between SIGRTMIN+0 ... SIGRTMIN+30
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering * (aka SIGRTMAX). */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering SIGUSR1, /* systemd/upstart: reconnect to D-Bus */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering SIGINT, /* Kernel sends us this on control-alt-del */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering SIGWINCH, /* Kernel sends us this on kbrequest (alt-arrowup) */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering SIGPWR, /* Some kernel drivers and upsd send us this on power failure */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering SIGRTMIN+0, /* systemd: start default.target */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering SIGRTMIN+1, /* systemd: isolate rescue.target */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering SIGRTMIN+2, /* systemd: isolate emergency.target */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering SIGRTMIN+3, /* systemd: start halt.target */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering SIGRTMIN+4, /* systemd: start poweroff.target */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering SIGRTMIN+5, /* systemd: start reboot.target */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering SIGRTMIN+6, /* systemd: start kexec.target */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* ... space for more special targets ... */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering SIGRTMIN+13, /* systemd: Immediate halt */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering SIGRTMIN+14, /* systemd: Immediate poweroff */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering SIGRTMIN+15, /* systemd: Immediate reboot */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering SIGRTMIN+16, /* systemd: Immediate kexec */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* ... space for more immediate system state changes ... */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering SIGRTMIN+20, /* systemd: enable status messages */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering SIGRTMIN+21, /* systemd: disable status messages */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering SIGRTMIN+22, /* systemd: set log level to LOG_DEBUG */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering SIGRTMIN+23, /* systemd: set log level to LOG_INFO */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering SIGRTMIN+24, /* systemd: Immediate exit (--user only) */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* .. one free signal here ... */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering#if !defined(__hppa64__) && !defined(__hppa__)
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* Apparently Linux on hppa has fewer RT
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering * signals (SIGRTMAX is SIGRTMIN+25 there),
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering * hence let's not try to make use of them
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering * here. Since these commands are accessible
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering * by different means and only really a safety
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering * net, the missing functionality on hppa
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering * shouldn't matter. */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering SIGRTMIN+26, /* systemd: set log target to journal-or-kmsg */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering SIGRTMIN+27, /* systemd: set log target to console */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering SIGRTMIN+28, /* systemd: set log target to kmsg */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering SIGRTMIN+29, /* systemd: set log target to syslog-or-kmsg (obsolete) */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* ... one free signal here SIGRTMIN+30 ... */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering m->signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering r = sd_event_add_io(m->event, &m->signal_event_source, m->signal_fd, EPOLLIN, manager_dispatch_signal_fd, m);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering (void) sd_event_source_set_description(m->signal_event_source, "manager-signal");
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* Process signals a bit earlier than the rest of things, but
249968612f16a71df909d6e73785c18a9ff36a65Lennart Poettering * later than notify_fd processing, so that the notify
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering * processing can still figure out to which process/service a
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering * message belongs, before we reap the process. */
a9cdc94f7ff40f22a3cf9472f612a80730a1b010Dave Reisner r = sd_event_source_set_priority(m->signal_event_source, SD_EVENT_PRIORITY_NORMAL-5);
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidtstatic void manager_clean_environment(Manager *m) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* Let's remove some environment variables that we
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen * need ourselves to communicate with our clients */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering "NOTIFY_SOCKET",
NULL);
assert(m);
NULL);
if (!m->environment)
return -ENOMEM;
Manager *m;
return -ENOMEM;
#ifdef ENABLE_EFI
m->default_tasks_accounting = true;
r = manager_default_environment(m);
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
r = manager_setup_signals(m);
goto fail;
r = manager_setup_cgroup(m);
goto fail;
r = manager_setup_time_change(m);
goto fail;
if (!m->udev) {
r = -ENOMEM;
goto fail;
*_m = m;
fail:
manager_free(m);
if (m->test_run)
if (m->notify_fd < 0) {
if (fd < 0)
return -EINVAL;
if (!m->notify_socket)
return log_oom();
if (!m->notify_event_source) {
r = sd_event_add_io(m->event, &m->notify_event_source, m->notify_fd, EPOLLIN, manager_dispatch_notify_fd, m);
assert(m);
if (!is_kdbus_available())
return -ESOCKTNOSUPPORT;
if (m->kdbus_fd < 0)
bool try_bus_connect;
assert(m);
if (m->test_run)
m->kdbus_fd >= 0 ||
reexecuting ||
Unit *u;
assert(m);
while ((u = m->cleanup_queue)) {
unit_free(u);
Iterator i;
bool is_bad;
assert(u);
if (u->in_cleanup_queue)
goto bad;
if (unit_check_gc(u))
goto good;
is_bad = true;
goto good;
is_bad = false;
if (is_bad)
goto bad;
bad:
good:
Unit *u;
unsigned gc_marker;
assert(m);
while ((u = m->gc_queue)) {
u->in_gc_queue = false;
if (u->id)
m->n_in_gc_queue = 0;
Unit *u;
assert(m);
unit_free(u);
m->n_on_console = 0;
m->n_running_jobs = 0;
UnitType c;
return NULL;
for (c = 0; c < _UNIT_TYPE_MAX; c++)
bus_done(m);
for (i = 0; i < _RLIMIT_MAX; i++)
free(m);
return NULL;
UnitType c;
assert(m);
for (c = 0; c < _UNIT_TYPE_MAX; c++) {
if (!unit_type_supported(c)) {
Iterator i;
Unit *u;
assert(m);
if (u->id != k)
r = unit_coldplug(u);
assert(m);
if (!m->unit_path_cache) {
d = opendir(*i);
r = -ENOMEM;
goto fail;
goto fail;
d = safe_closedir(d);
fail:
Iterator i;
Unit *u;
assert(m);
assert(m);
r = manager_run_generators(m);
r = lookup_paths_init(
NULL,
if (serialization)
m->n_reloading ++;
if (serialization)
q = manager_setup_notify(m);
manager_coldplug(m);
if (serialization) {
m->n_reloading --;
m->send_reloading_done = true;
int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, sd_bus_error *e, Job **_ret) {
assert(m);
return sd_bus_error_setf(e, BUS_ERROR_NO_ISOLATION, "Operation refused, unit may not be isolated.");
log_unit_debug(unit, "Trying to enqueue job %s/%s/%s", unit->id, job_type_to_string(type), job_mode_to_string(mode));
if (!tr)
return -ENOMEM;
goto tr_abort;
goto tr_abort;
goto tr_abort;
if (_ret)
int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, sd_bus_error *e, Job **ret) {
assert(m);
int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Job **ret) {
assert(m);
return log_warning_errno(r, "Failed to enqueue %s job for %s: %s", job_mode_to_string(mode), name, bus_error_message(&error, r));
assert(m);
assert(m);
Unit *u;
assert(m);
if (m->dispatching_load_queue)
m->dispatching_load_queue = true;
while ((u = m->load_queue)) {
unit_load(u);
m->dispatching_load_queue = false;
Manager *m,
const char *name,
const char *path,
sd_bus_error *e,
UnitType t;
assert(m);
if (!name)
if (ret) {
if (!ret)
return -ENOMEM;
if (path) {
return -ENOMEM;
if (_ret)
int manager_load_unit(
Manager *m,
const char *name,
const char *path,
sd_bus_error *e,
assert(m);
if (_ret)
Iterator i;
Job *j;
assert(s);
assert(f);
Iterator i;
Unit *u;
assert(s);
assert(f);
if (u->id == t)
Job *j;
assert(m);
Job *j;
assert(m);
while ((j = m->run_queue)) {
if (m->n_running_jobs > 0)
if (m->n_on_console > 0)
Job *j;
Unit *u;
assert(m);
if (m->dispatching_dbus_queue)
m->dispatching_dbus_queue = true;
while ((u = m->dbus_unit_queue)) {
while ((j = m->dbus_job_queue)) {
m->dispatching_dbus_queue = false;
if (m->send_reloading_done) {
m->send_reloading_done = false;
bus_manager_send_reloading(m, false);
if (m->queued_message)
static void manager_invoke_notify_message(Manager *m, Unit *u, pid_t pid, const char *buf, size_t n, FDSet *fds) {
assert(m);
assert(u);
assert(n > 0);
if (!tags) {
log_oom();
static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
} control = {};
bool found = false;
unsigned n_fds = 0;
ssize_t n;
assert(m);
return -errno;
if (n_fds > 0) {
return log_oom();
buf[n] = 0;
if (u1) {
found = true;
found = true;
found = true;
if (!found)
assert(m);
assert(u);
assert(m);
return -errno;
if (u1)
return -errno;
static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
ssize_t n;
bool sigchld = false;
assert(m);
if (n != sizeof(sfsi)) {
return -EIO;
return -errno;
&sfsi);
case SIGCHLD:
sigchld = true;
case SIGTERM:
case SIGINT:
status_printf(NULL, true, false, "Ctrl-Alt-Del was pressed more than 7 times within 2s, rebooting immediately.");
case SIGWINCH:
case SIGPWR:
case SIGUSR1: {
Unit *u;
bus_init(m, true);
case SIGUSR2: {
r = fflush_and_check(f);
case SIGHUP:
static const char * const target_table[] = {
[0] = SPECIAL_DEFAULT_TARGET,
[0] = MANAGER_HALT,
if (sigchld)
static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
Iterator i;
Unit *u;
assert(m);
NULL);
static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
assert(m);
static int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata) {
assert(m);
assert(m);
r = manager_dispatch_sigchld(m);
if (manager_dispatch_load_queue(m) > 0)
if (manager_dispatch_gc_queue(m) > 0)
if (manager_dispatch_cleanup_queue(m) > 0)
if (manager_dispatch_cgroup_queue(m) > 0)
if (manager_dispatch_dbus_queue(m) > 0)
if (wait_usec <= 0)
return m->exit_code;
Unit *u;
assert(m);
assert(s);
r = unit_name_from_dbus_path(s, &n);
*_u = u;
unsigned id;
Job *j;
assert(m);
assert(s);
return -EINVAL;
return -ENOENT;
*_j = j;
#ifdef HAVE_AUDIT
const char *msg;
int audit_fd, r;
if (audit_fd < 0)
if (m->n_reloading > 0)
if (m->n_reloading > 0)
if (detect_container() > 0)
if (fd < 0) {
if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) {
log_oom();
errno = 0;
const char *path;
FILE *f;
if (fd < 0)
return -errno;
return -errno;
*_f = f;
Iterator i;
Unit *u;
assert(m);
assert(f);
m->n_reloading ++;
if (!in_initrd()) {
if (!switching_root) {
if (!ce)
return -ENOMEM;
if (m->notify_fd >= 0) {
int copy;
if (copy < 0)
return copy;
if (m->kdbus_fd >= 0) {
int copy;
if (copy < 0)
return copy;
if (u->id != t)
m->n_reloading --;
m->n_reloading --;
if (ferror(f))
return -EIO;
assert(m);
assert(f);
m->n_reloading ++;
if (feof(f))
r = -errno;
goto finish;
uint32_t n;
m->n_installed_jobs += n;
uint32_t n;
m->n_failed_jobs += n;
goto finish;
r = -ENOMEM;
goto finish;
m->environment = e;
int fd;
r = -ENOMEM;
goto finish;
m->notify_socket = n;
int fd;
Unit *u;
if (feof(f))
r = -errno;
goto finish;
goto finish;
goto finish;
if (ferror(f))
r = -EIO;
m->n_reloading --;
assert(m);
r = manager_open_serialization(m, &f);
m->n_reloading ++;
bus_manager_send_reloading(m, true);
if (!fds) {
m->n_reloading --;
return -ENOMEM;
m->n_reloading --;
m->n_reloading --;
return -errno;
q = manager_run_generators(m);
q = lookup_paths_init(
NULL,
fclose(f);
f = NULL;
q = manager_setup_notify(m);
manager_coldplug(m);
if (m->api_bus)
m->n_reloading--;
m->send_reloading_done = true;
assert(m);
return m->n_reloading != 0;
Unit *u;
Iterator i;
assert(m);
Unit *u;
assert(m);
return unit_inactive_or_pending(u);
char userspace[FORMAT_TIMESPAN_MAX], initrd[FORMAT_TIMESPAN_MAX], kernel[FORMAT_TIMESPAN_MAX], sum[FORMAT_TIMESPAN_MAX];
if (m->test_run)
NULL);
initrd_usec = 0;
NULL);
NULL);
bus_manager_send_finished(m, firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec);
sd_notifyf(false,
assert(m);
if (m->n_reloading > 0)
if (m->jobs_in_progress_event_source)
(void) sd_event_source_set_time(m->jobs_in_progress_event_source, now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_WAIT_USEC);
manager_flip_auto_status(m, false);
m->confirm_spawn = false;
manager_set_first_boot(m, false);
assert(m);
if (*generator)
return log_oom();
free(p);
const char *s = NULL;
return -EINVAL;
return log_oom();
free(p);
return log_oom();
if (!mkdtemp(p)) {
free(p);
return -errno;
*generator = p;
assert(m);
if (!*generator)
char **path;
assert(m);
if (m->test_run)
if (!paths)
return log_oom();
goto found;
goto finish;
goto finish;
goto finish;
assert(m);
if (!*generator)
assert(m);
assert(m);
l = m->environment;
return -ENOMEM;
strv_free(a);
return -ENOMEM;
if (m->environment != l)
strv_free(a);
strv_free(b);
m->environment = l;
assert(m);
for (i = 0; i < _RLIMIT_MAX; i++) {
if (!default_rlimit[i])
if (!m->rlimit[i])
return -ENOMEM;
Unit *u;
assert(m);
log_open();
assert(m);
if (mode > 0)
assert(m);
if (m->no_console_output)
if (m->show_status > 0)
assert(m);
if (m->first_boot != (int) b) {
m->first_boot = b;
void manager_status_printf(Manager *m, StatusType type, const char *status, const char *format, ...) {
assert(m);
assert(m);
unsigned size;
assert(m);
if (failed) {
return log_oom();
return log_oom();
Unit *u;
assert(m);
return MANAGER_INITIALIZING;
return MANAGER_STARTING;
return MANAGER_STOPPING;
return MANAGER_MAINTENANCE;
return MANAGER_MAINTENANCE;
return MANAGER_DEGRADED;
return MANAGER_RUNNING;