manager.c revision ae2a2c53dd059f0f20fa8080f6b67389be3d3e89
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen This file is part of systemd.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen Copyright 2010 Lennart Poettering
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen systemd is free software; you can redistribute it and/or modify it
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen under the terms of the GNU Lesser General Public License as published by
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen the Free Software Foundation; either version 2.1 of the License, or
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen (at your option) any later version.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen systemd is distributed in the hope that it will be useful, but
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen Lesser General Public License for more details.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen You should have received a copy of the GNU Lesser General Public License
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen/* Initial delay and the interval for printing status messages about running jobs */
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen#define JOBS_IN_PROGRESS_WAIT_USEC (5*USEC_PER_SEC)
977085794d2996320e345433403de75f662b0622Tom Gundersen#define JOBS_IN_PROGRESS_PERIOD_USEC (USEC_PER_SEC / 3)
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersenstatic int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenstatic int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
5b9d4dc05560ddda89e48b6b39365824b15e1300Tom Gundersenstatic int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
5b9d4dc05560ddda89e48b6b39365824b15e1300Tom Gundersenstatic int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenstatic int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenstatic int manager_dispatch_run_queue(sd_event_source *source, void *userdata);
977085794d2996320e345433403de75f662b0622Tom Gundersenstatic void manager_undo_generators(Manager *m);
977085794d2996320e345433403de75f662b0622Tom Gundersenstatic void manager_watch_jobs_in_progress(Manager *m) {
977085794d2996320e345433403de75f662b0622Tom Gundersen next = now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_WAIT_USEC;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen (void) sd_event_source_set_description(m->jobs_in_progress_event_source, "manager-jobs-in-progress");
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen#define CYLON_BUFFER_EXTRA (2*(sizeof(ANSI_RED_ON)-1) + sizeof(ANSI_HIGHLIGHT_RED_ON)-1 + 2*(sizeof(ANSI_HIGHLIGHT_OFF)-1))
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenstatic void draw_cylon(char buffer[], size_t buflen, unsigned width, unsigned pos) {
d2df0d0ed3a88e491405b403e6022e6619750130Tom Gundersen assert(buflen >= CYLON_BUFFER_EXTRA + width + 1);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen assert(pos <= width+1); /* 0 or width+1 mean that the center light is behind the corner */
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenvoid manager_flip_auto_status(Manager *m, bool enable) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen manager_set_show_status(m, SHOW_STATUS_TEMPORARY);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenstatic void manager_print_jobs_in_progress(Manager *m) {
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen char time[FORMAT_TIMESPAN_MAX], limit[FORMAT_TIMESPAN_MAX] = "no limit";
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen print_nr = (m->jobs_in_progress_iteration / JOBS_IN_PROGRESS_PERIOD_DIVISOR) % m->n_running_jobs;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (j->state == JOB_RUNNING && counter++ == print_nr)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen /* m->n_running_jobs must be consistent with the contents of m->jobs,
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen * so the above loop must have succeeded in finding j. */
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen cylon_pos = m->jobs_in_progress_iteration % 14;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen draw_cylon(cylon, sizeof(cylon), 6, cylon_pos);
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen if (asprintf(&job_of_n, "(%u of %u) ", counter, m->n_running_jobs) < 0)
74df0fca09b3c31ed19e14ba80f996fdff772417Lennart Poettering format_timespan(time, sizeof(time), now(CLOCK_MONOTONIC) - j->begin_usec, 1*USEC_PER_SEC);
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen format_timespan(limit, sizeof(limit), x - j->begin_usec, 1*USEC_PER_SEC);
ff83aac3647e21f31ac5e2b575ec1285dc585f6bTom Gundersen manager_status_printf(m, STATUS_TYPE_EPHEMERAL, cylon,
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen "%sA %s job is running for %s (%s / %s)",
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenstatic int have_ask_password(void) {
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen return false;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return false;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenstatic int manager_dispatch_ask_password_fd(sd_event_source *source,
edbb03e95a3c31bf719d5c6c46eec14d0bcb9c8fTom Gundersen /* Log error but continue. Negative have_ask_password
edbb03e95a3c31bf719d5c6c46eec14d0bcb9c8fTom Gundersen * is treated as unknown status. */
edbb03e95a3c31bf719d5c6c46eec14d0bcb9c8fTom Gundersen log_error_errno(m->have_ask_password, "Failed to list /run/systemd/ask-password: %m");
b3e013148603aa670bc2c060ac63d48e54d76fc2Tom Gundersenstatic void manager_close_ask_password(Manager *m) {
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen m->ask_password_event_source = sd_event_source_unref(m->ask_password_event_source);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen m->ask_password_inotify_fd = safe_close(m->ask_password_inotify_fd);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenstatic int manager_check_ask_password(Manager *m) {
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen mkdir_p_label("/run/systemd/ask-password", 0755);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen m->ask_password_inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen return log_error_errno(errno, "inotify_init1() failed: %m");
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen if (inotify_add_watch(m->ask_password_inotify_fd, "/run/systemd/ask-password", IN_CREATE|IN_DELETE|IN_MOVE) < 0) {
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen log_error_errno(errno, "Failed to add watch on /run/systemd/ask-password: %m");
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen r = sd_event_add_io(m->event, &m->ask_password_event_source,
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen log_error_errno(errno, "Failed to add event source for /run/systemd/ask-password: %m");
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen (void) sd_event_source_set_description(m->ask_password_event_source, "manager-ask-password");
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen /* Queries might have been added meanwhile... */
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen manager_dispatch_ask_password_fd(m->ask_password_event_source,
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poetteringstatic int manager_watch_idle_pipe(Manager *m) {
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen r = sd_event_add_io(m->event, &m->idle_pipe_event_source, m->idle_pipe[2], EPOLLIN, manager_dispatch_idle_pipe_fd, m);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen return log_error_errno(r, "Failed to watch idle pipe: %m");
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen (void) sd_event_source_set_description(m->idle_pipe_event_source, "manager-idle-pipe");
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersenstatic void manager_close_idle_pipe(Manager *m) {
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersenstatic int manager_setup_time_change(Manager *m) {
55428d84f31b52da1c50b7469f14e15740547f20Tom Gundersen /* We only care for the cancellation event, hence we set the
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering * timeout to the latest possible value. */
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen assert_cc(sizeof(time_t) == sizeof(TIME_T_MAX));
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen /* Uses TFD_TIMER_CANCEL_ON_SET to get notifications whenever
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen * CLOCK_REALTIME makes a jump relative to CLOCK_MONOTONIC */
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen m->time_change_fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen return log_error_errno(errno, "Failed to create timerfd: %m");
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen if (timerfd_settime(m->time_change_fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0) {
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen log_debug_errno(errno, "Failed to set up TFD_TIMER_CANCEL_ON_SET, ignoring: %m");
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen m->time_change_fd = safe_close(m->time_change_fd);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen r = sd_event_add_io(m->event, &m->time_change_event_source, m->time_change_fd, EPOLLIN, manager_dispatch_time_change_fd, m);
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen return log_error_errno(r, "Failed to create time change event source: %m");
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen (void) sd_event_source_set_description(m->time_change_event_source, "manager-time-change");
977085794d2996320e345433403de75f662b0622Tom Gundersen log_debug("Set up TFD_TIMER_CANCEL_ON_SET timerfd.");
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersenstatic int enable_special_signals(Manager *m) {
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen /* Enable that we get SIGINT on control-alt-del. In containers
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen * this will fail with EPERM (older) or EINVAL (newer), so
a501033335ed402c8f7e86fe41a15531ba69abd7Tom Gundersen * ignore that. */
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen if (reboot(RB_DISABLE_CAD) < 0 && errno != EPERM && errno != EINVAL)
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen log_warning_errno(errno, "Failed to enable ctrl-alt-del handling: %m");
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen /* Support systems without virtual console */
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen log_warning_errno(errno, "Failed to open /dev/tty0: %m");
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen /* Enable that we get SIGWINCH on kbrequest */
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen log_warning_errno(errno, "Failed to enable kbrequest handling: %m");
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen /* We make liberal use of realtime signals here. On
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen * Linux/glibc we have 30 of them (with the exception of Linux
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen * on hppa, see below), between SIGRTMIN+0 ... SIGRTMIN+30
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen * (aka SIGRTMAX). */
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen SIGUSR1, /* systemd/upstart: reconnect to D-Bus */
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen SIGINT, /* Kernel sends us this on control-alt-del */
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen SIGWINCH, /* Kernel sends us this on kbrequest (alt-arrowup) */
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen SIGPWR, /* Some kernel drivers and upsd send us this on power failure */
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen SIGRTMIN+0, /* systemd: start default.target */
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen SIGRTMIN+1, /* systemd: isolate rescue.target */
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen SIGRTMIN+2, /* systemd: isolate emergency.target */
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen SIGRTMIN+4, /* systemd: start poweroff.target */
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen SIGRTMIN+5, /* systemd: start reboot.target */
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen /* ... space for more special targets ... */
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen SIGRTMIN+14, /* systemd: Immediate poweroff */
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen /* ... space for more immediate system state changes ... */
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen SIGRTMIN+20, /* systemd: enable status messages */
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen SIGRTMIN+21, /* systemd: disable status messages */
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen SIGRTMIN+22, /* systemd: set log level to LOG_DEBUG */
d2df0d0ed3a88e491405b403e6022e6619750130Tom Gundersen SIGRTMIN+23, /* systemd: set log level to LOG_INFO */
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen SIGRTMIN+24, /* systemd: Immediate exit (--user only) */
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen /* .. one free signal here ... */
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen /* Apparently Linux on hppa has fewer RT
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen * signals (SIGRTMAX is SIGRTMIN+25 there),
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen * hence let's not try to make use of them
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen * here. Since these commands are accessible
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen * by different means and only really a safety
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen * net, the missing functionality on hppa
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen * shouldn't matter. */
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen SIGRTMIN+26, /* systemd: set log target to journal-or-kmsg */
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen SIGRTMIN+27, /* systemd: set log target to console */
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen SIGRTMIN+28, /* systemd: set log target to kmsg */
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen SIGRTMIN+29, /* systemd: set log target to syslog-or-kmsg (obsolete) */
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen /* ... one free signal here SIGRTMIN+30 ... */
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen m->signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
r = sd_event_add_io(m->event, &m->signal_event_source, m->signal_fd, EPOLLIN, manager_dispatch_signal_fd, m);
return enable_special_signals(m);
assert(m);
m->environment,
NULL);
assert(m);
NULL);
if (!m->environment)
return -ENOMEM;
Manager *m;
return -ENOMEM;
#ifdef ENABLE_EFI
m->pin_cgroupfs_fd = m->notify_fd = m->signal_fd = m->time_change_fd = m->dev_autofs_fd = m->private_listen_fd = m->kdbus_fd = m->utab_inotify_fd = -1;
r = manager_default_environment(m);
goto fail;
goto fail;
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;
closedir(d);
d = NULL;
fail:
Unit *u;
Iterator i;
assert(m);
assert(m);
r = manager_run_generators(m);
r = lookup_paths_init(
NULL,
if (serialization)
m->n_reloading ++;
r = manager_enumerate(m);
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, bool override, 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, bool override, sd_bus_error *e, Job **_ret) {
assert(m);
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, 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) {
ssize_t n;
assert(m);
} control = {};
bool found = false;
unsigned n_fds = 0;
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 (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,
q = manager_enumerate(m);
fclose(f);
f = NULL;
q = manager_setup_notify(m);
manager_coldplug(m);
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,
Iterator i;
assert(m);
if (m->n_reloading > 0)
if (m->jobs_in_progress_event_source)
manager_flip_auto_status(m, false);
m->confirm_spawn = false;
manager_set_first_boot(m, false);
if (u->cgroup_path)
cgroup_context_apply(unit_get_cgroup_context(u), unit_get_cgroup_mask(u), u->cgroup_path, manager_state(m));
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);
if (!found) {
assert(m);
assert(m);
unsigned size;
assert(m);
if (failed) {
log_oom();
Unit *u;
assert(m);
return MANAGER_INITIALIZING;
return MANAGER_STARTING;
if (u && u->job && IN_SET(u->job->type, JOB_START, JOB_RESTART, JOB_TRY_RESTART, JOB_RELOAD_OR_START))
return MANAGER_STOPPING;
return MANAGER_MAINTENANCE;
return MANAGER_MAINTENANCE;
return MANAGER_DEGRADED;
return MANAGER_RUNNING;