manager.c revision 9a636ed8096fa44927f182ac3eaef4104866d4a9
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer/***
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer This file is part of systemd.
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer Copyright 2010 Lennart Poettering
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer systemd is free software; you can redistribute it and/or modify it
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer under the terms of the GNU Lesser General Public License as published by
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier the Free Software Foundation; either version 2.1 of the License, or
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier (at your option) any later version.
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier systemd is distributed in the hope that it will be useful, but
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier WITHOUT ANY WARRANTY; without even the implied warranty of
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier Lesser General Public License for more details.
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier You should have received a copy of the GNU Lesser General Public License
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier along with systemd; If not, see <http://www.gnu.org/licenses/>.
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier***/
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <assert.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <errno.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <string.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <signal.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <sys/wait.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <unistd.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <sys/poll.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <sys/reboot.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <sys/ioctl.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <linux/kd.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <termios.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <fcntl.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <sys/types.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <sys/stat.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <dirent.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <sys/timerfd.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier#ifdef HAVE_AUDIT
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <libaudit.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#endif
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "sd-daemon.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "sd-id128.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "sd-messages.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "manager.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "transaction.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "hashmap.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "macro.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "strv.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "log.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "util.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "mkdir.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "ratelimit.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "locale-setup.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "mount-setup.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "unit-name.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "missing.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "path-lookup.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "special.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "exit-status.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "virt.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "watchdog.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "cgroup-util.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "path-util.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "audit-fd.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "boot-timestamps.h"
8a8332f77e61d41f3bb28b8f929ed41e0ffaf721Zbigniew Jędrzejewski-Szmek#include "env-util.h"
8a8332f77e61d41f3bb28b8f929ed41e0ffaf721Zbigniew Jędrzejewski-Szmek#include "bus-errors.h"
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier#include "bus-error.h"
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier#include "bus-util.h"
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier#include "dbus.h"
8a8332f77e61d41f3bb28b8f929ed41e0ffaf721Zbigniew Jędrzejewski-Szmek#include "dbus-unit.h"
8a8332f77e61d41f3bb28b8f929ed41e0ffaf721Zbigniew Jędrzejewski-Szmek#include "dbus-job.h"
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier#include "dbus-manager.h"
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier#include "bus-kernel.h"
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier/* As soon as 5s passed since a unit was added to our GC queue, make sure to run a gc sweep */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier#define GC_QUEUE_USEC_MAX (10*USEC_PER_SEC)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier/* Initial delay and the interval for printing status messages about running jobs */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier#define JOBS_IN_PROGRESS_WAIT_SEC 5
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier#define JOBS_IN_PROGRESS_PERIOD_SEC 1
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier#define JOBS_IN_PROGRESS_PERIOD_DIVISOR 3
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier/* Where clients shall send notification messages to */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier#define NOTIFY_SOCKET "@/org/freedesktop/systemd1/notify"
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier#define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierstatic int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierstatic int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierstatic int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierstatic int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierstatic int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierstatic int manager_dispatch_run_queue(sd_event_source *source, void *userdata);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierstatic int manager_setup_notify(Manager *m) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier union {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier struct sockaddr sa;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier struct sockaddr_un un;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier } sa = {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier .sa.sa_family = AF_UNIX,
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier };
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier int one = 1, r;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier m->notify_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (m->notify_fd < 0) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_error("Failed to allocate notification socket: %m");
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
8a8332f77e61d41f3bb28b8f929ed41e0ffaf721Zbigniew Jędrzejewski-Szmek
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (getpid() != 1 || detect_container(NULL) > 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier snprintf(sa.un.sun_path, sizeof(sa.un.sun_path), NOTIFY_SOCKET "/%llu", random_ull());
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier else
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier strncpy(sa.un.sun_path, NOTIFY_SOCKET, sizeof(sa.un.sun_path));
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier sa.un.sun_path[0] = 0;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = bind(m->notify_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1));
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (r < 0) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_error("bind() failed: %m");
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = setsockopt(m->notify_fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (r < 0) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_error("SO_PASSCRED failed: %m");
739d81ddd005fae2bb82edce5b8a6173c7c48b34Zbigniew Jędrzejewski-Szmek return -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
b8667ee4162cd2510363602b417cecede9fd2ccaZbigniew Jędrzejewski-Szmek
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = sd_event_add_io(m->event, m->notify_fd, EPOLLIN, manager_dispatch_notify_fd, m, &m->notify_event_source);
739d81ddd005fae2bb82edce5b8a6173c7c48b34Zbigniew Jędrzejewski-Szmek if (r < 0) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_error("Failed to allocate notify event source: %s", strerror(-r));
b8667ee4162cd2510363602b417cecede9fd2ccaZbigniew Jędrzejewski-Szmek return -errno;
b8667ee4162cd2510363602b417cecede9fd2ccaZbigniew Jędrzejewski-Szmek }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier sa.un.sun_path[0] = '@';
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier m->notify_socket = strdup(sa.un.sun_path);
739d81ddd005fae2bb82edce5b8a6173c7c48b34Zbigniew Jędrzejewski-Szmek if (!m->notify_socket)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return log_oom();
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_debug("Using notification socket %s", m->notify_socket);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return 0;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier}
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierstatic int manager_watch_jobs_in_progress(Manager *m) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(m);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (m->jobs_in_progress_event_source)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return 0;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return sd_event_add_monotonic(m->event, JOBS_IN_PROGRESS_WAIT_SEC, 0, manager_dispatch_jobs_in_progress, m, &m->jobs_in_progress_event_source);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier}
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier#define CYLON_BUFFER_EXTRA (2*(sizeof(ANSI_RED_ON)-1) + sizeof(ANSI_HIGHLIGHT_RED_ON)-1 + 2*(sizeof(ANSI_HIGHLIGHT_OFF)-1))
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierstatic void draw_cylon(char buffer[], size_t buflen, unsigned width, unsigned pos) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier char *p = buffer;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(buflen >= CYLON_BUFFER_EXTRA + width + 1);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(pos <= width+1); /* 0 or width+1 mean that the center light is behind the corner */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (pos > 1) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (pos > 2)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier p = mempset(p, ' ', pos-2);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier p = stpcpy(p, ANSI_RED_ON);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier *p++ = '*';
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (pos > 0 && pos <= width) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier p = stpcpy(p, ANSI_HIGHLIGHT_RED_ON);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier *p++ = '*';
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier p = stpcpy(p, ANSI_HIGHLIGHT_OFF);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (pos < width) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier p = stpcpy(p, ANSI_RED_ON);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier *p++ = '*';
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (pos < width-1)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier p = mempset(p, ' ', width-1-pos);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier strcpy(p, ANSI_HIGHLIGHT_OFF);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier}
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierstatic void manager_print_jobs_in_progress(Manager *m) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier _cleanup_free_ char *job_of_n = NULL;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier Iterator i;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier Job *j;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier unsigned counter = 0, print_nr;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier char cylon[6 + CYLON_BUFFER_EXTRA + 1];
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier unsigned cylon_pos;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(m);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier print_nr = (m->jobs_in_progress_iteration / JOBS_IN_PROGRESS_PERIOD_DIVISOR) % m->n_running_jobs;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier HASHMAP_FOREACH(j, m->jobs, i)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (j->state == JOB_RUNNING && counter++ == print_nr)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier break;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier /* m->n_running_jobs must be consistent with the contents of m->jobs,
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * so the above loop must have succeeded in finding j. */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(counter == print_nr + 1);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(j);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier cylon_pos = m->jobs_in_progress_iteration % 14;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (cylon_pos >= 8)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier cylon_pos = 14 - cylon_pos;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier draw_cylon(cylon, sizeof(cylon), 6, cylon_pos);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (m->n_running_jobs > 1)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (asprintf(&job_of_n, "(%u of %u) ", counter, m->n_running_jobs) < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier job_of_n = NULL;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier manager_status_printf(m, true, cylon, "%sA %s job is running for %s",
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier strempty(job_of_n), job_type_to_string(j->type), unit_description(j->unit));
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier m->jobs_in_progress_iteration++;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier}
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierstatic int manager_watch_idle_pipe(Manager *m) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier int r;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(m);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (m->idle_pipe_event_source)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return 0;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (m->idle_pipe[2] < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return 0;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = sd_event_add_io(m->event, m->idle_pipe[2], EPOLLIN, manager_dispatch_idle_pipe_fd, m, &m->idle_pipe_event_source);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (r < 0) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_error("Failed to watch idle pipe: %s", strerror(-r));
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return r;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return 0;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier}
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierstatic void manager_close_idle_pipe(Manager *m) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(m);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier close_pipe(m->idle_pipe);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier close_pipe(m->idle_pipe + 2);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier}
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierstatic int manager_setup_time_change(Manager *m) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier int r;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier /* We only care for the cancellation event, hence we set the
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * timeout to the latest possible value. */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier struct itimerspec its = {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier .it_value.tv_sec = TIME_T_MAX,
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier };
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(m);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert_cc(sizeof(time_t) == sizeof(TIME_T_MAX));
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier /* Uses TFD_TIMER_CANCEL_ON_SET to get notifications whenever
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * CLOCK_REALTIME makes a jump relative to CLOCK_MONOTONIC */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier m->time_change_fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (m->time_change_fd < 0) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_error("Failed to create timerfd: %m");
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (timerfd_settime(m->time_change_fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_debug("Failed to set up TFD_TIMER_CANCEL_ON_SET, ignoring: %m");
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier close_nointr_nofail(m->time_change_fd);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier m->time_change_fd = -1;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return 0;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = sd_event_add_io(m->event, m->time_change_fd, EPOLLIN, manager_dispatch_time_change_fd, m, &m->time_change_event_source);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (r < 0) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_error("Failed to create time change event source: %s", strerror(-r));
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return r;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_debug("Set up TFD_TIMER_CANCEL_ON_SET timerfd.");
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return 0;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier}
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierstatic int enable_special_signals(Manager *m) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier _cleanup_close_ int fd = -1;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(m);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier /* Enable that we get SIGINT on control-alt-del. In containers
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * this will fail with EPERM (older) or EINVAL (newer), so
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * ignore that. */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (reboot(RB_DISABLE_CAD) < 0 && errno != EPERM && errno != EINVAL)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_warning("Failed to enable ctrl-alt-del handling: %m");
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (fd < 0) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier /* Support systems without virtual console */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (fd != -ENOENT)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_warning("Failed to open /dev/tty0: %m");
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier } else {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer /* Enable that we get SIGWINCH on kbrequest */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (ioctl(fd, KDSIGACCEPT, SIGWINCH) < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_warning("Failed to enable kbrequest handling: %m");
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer return 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerstatic int manager_setup_signals(Manager *m) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer struct sigaction sa = {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer .sa_handler = SIG_DFL,
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer .sa_flags = SA_NOCLDSTOP|SA_RESTART,
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer };
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer sigset_t mask;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer int r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* We are not interested in SIGSTOP and friends. */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert_se(sigemptyset(&mask) == 0);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer sigset_add_many(&mask,
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGCHLD, /* Child died */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGTERM, /* Reexecute daemon */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGHUP, /* Reload configuration */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGUSR1, /* systemd/upstart: reconnect to D-Bus */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGUSR2, /* systemd: dump status */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGINT, /* Kernel sends us this on control-alt-del */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGWINCH, /* Kernel sends us this on kbrequest (alt-arrowup) */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGPWR, /* Some kernel drivers and upsd send us this on power failure */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGRTMIN+0, /* systemd: start default.target */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGRTMIN+1, /* systemd: isolate rescue.target */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGRTMIN+2, /* systemd: isolate emergency.target */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGRTMIN+3, /* systemd: start halt.target */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGRTMIN+4, /* systemd: start poweroff.target */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGRTMIN+5, /* systemd: start reboot.target */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGRTMIN+6, /* systemd: start kexec.target */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGRTMIN+13, /* systemd: Immediate halt */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGRTMIN+14, /* systemd: Immediate poweroff */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGRTMIN+15, /* systemd: Immediate reboot */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGRTMIN+16, /* systemd: Immediate kexec */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGRTMIN+20, /* systemd: enable status messages */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGRTMIN+21, /* systemd: disable status messages */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGRTMIN+22, /* systemd: set log level to LOG_DEBUG */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGRTMIN+23, /* systemd: set log level to LOG_INFO */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGRTMIN+24, /* systemd: Immediate exit (--user only) */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGRTMIN+26, /* systemd: set log target to journal-or-kmsg */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGRTMIN+27, /* systemd: set log target to console */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGRTMIN+28, /* systemd: set log target to kmsg */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SIGRTMIN+29, /* systemd: set log target to syslog-or-kmsg */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier -1);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier m->signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (m->signal_fd < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return -errno;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = sd_event_add_io(m->event, m->signal_fd, EPOLLIN, manager_dispatch_signal_fd, m, &m->signal_event_source);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* Process signals a bit earlier than the rest of things */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = sd_event_source_set_priority(m->signal_event_source, -5);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (m->running_as == SYSTEMD_SYSTEM)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return enable_special_signals(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerstatic int manager_default_environment(Manager *m) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (m->running_as == SYSTEMD_SYSTEM) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* The system manager always starts with a clean
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * environment for its children. It does not import
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * the kernel or the parents exported variables.
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer *
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * The initial passed environ is untouched to keep
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * /proc/self/environ valid; it is used for tagging
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * the init process inside containers. */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer m->environment = strv_new("PATH=" DEFAULT_PATH,
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer NULL);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* Import locale variables LC_*= from configuration */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer locale_setup(&m->environment);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer } else
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* The user manager passes its own environment
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * along to its children. */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer m->environment = strv_copy(environ);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (!m->environment)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return -ENOMEM;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer strv_sort(m->environment);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerstatic int manager_setup_kdbus(Manager *m) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer _cleanup_free_ char *p = NULL;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer#ifdef ENABLE_KDBUS
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (m->kdbus_fd >= 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* If there's already a bus address set, don't set up kdbus */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (m->running_as == SYSTEMD_USER && getenv("DBUS_SESSION_BUS_ADDRESS"))
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer m->kdbus_fd = bus_kernel_create_bus(m->running_as == SYSTEMD_SYSTEM ? "system" : "user", &p);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (m->kdbus_fd < 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_debug("Failed to set up kdbus: %s", strerror(-m->kdbus_fd));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return m->kdbus_fd;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_debug("Successfully set up kdbus on %s", p);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer#endif
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer return 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerstatic int manager_connect_bus(Manager *m, bool reexecuting) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer bool try_bus_connect;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer try_bus_connect =
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer m->kdbus_fd >= 0 ||
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer reexecuting ||
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer (m->running_as == SYSTEMD_USER && getenv("DBUS_SESSION_BUS_ADDRESS"));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* Try to connect to the busses, if possible. */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return bus_init(m, try_bus_connect);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerint manager_new(SystemdRunningAs running_as, Manager **_m) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer Manager *m;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer int r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(_m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(running_as >= 0);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(running_as < _SYSTEMD_RUNNING_AS_MAX);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer m = new0(Manager, 1);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (!m)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return -ENOMEM;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer#ifdef ENABLE_EFI
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (detect_container(NULL) <= 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer boot_timestamps(&m->userspace_timestamp, &m->firmware_timestamp, &m->loader_timestamp);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer#endif
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer m->running_as = running_as;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer m->exit_code = _MANAGER_EXIT_CODE_INVALID;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer m->idle_pipe[0] = m->idle_pipe[1] = m->idle_pipe[2] = m->idle_pipe[3] = -1;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer 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 = -1;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = manager_default_environment(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto fail;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = hashmap_ensure_allocated(&m->units, string_hash_func, string_compare_func);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto fail;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = hashmap_ensure_allocated(&m->jobs, trivial_hash_func, trivial_compare_func);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto fail;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = hashmap_ensure_allocated(&m->cgroup_unit, string_hash_func, string_compare_func);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto fail;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = hashmap_ensure_allocated(&m->watch_pids, trivial_hash_func, trivial_compare_func);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto fail;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = hashmap_ensure_allocated(&m->watch_bus, string_hash_func, string_compare_func);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto fail;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = sd_event_default(&m->event);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto fail;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = sd_event_add_defer(m->event, manager_dispatch_run_queue, m, &m->run_queue_event_source);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto fail;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = sd_event_source_set_priority(m->run_queue_event_source, SD_EVENT_PRIORITY_IDLE);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto fail;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = sd_event_source_set_enabled(m->run_queue_event_source, SD_EVENT_OFF);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto fail;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = manager_setup_signals(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto fail;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = manager_setup_cgroup(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto fail;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = manager_setup_notify(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto fail;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = manager_setup_time_change(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto fail;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer m->udev = udev_new();
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (!m->udev) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = -ENOMEM;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto fail;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer m->taint_usr = dir_is_empty("/usr") > 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer *_m = m;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerfail:
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer manager_free(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerstatic unsigned manager_dispatch_cleanup_queue(Manager *m) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer Unit *u;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer unsigned n = 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer while ((u = m->cleanup_queue)) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(u->in_cleanup_queue);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer unit_free(u);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer n++;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return n;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerenum {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer GC_OFFSET_IN_PATH, /* This one is on the path we were traveling */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer GC_OFFSET_UNSURE, /* No clue */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer GC_OFFSET_GOOD, /* We still need this unit */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer GC_OFFSET_BAD, /* We don't need this unit anymore */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer _GC_OFFSET_MAX
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer};
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerstatic void unit_gc_sweep(Unit *u, unsigned gc_marker) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer Iterator i;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer Unit *other;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer bool is_bad;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(u);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (u->gc_marker == gc_marker + GC_OFFSET_GOOD ||
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer u->gc_marker == gc_marker + GC_OFFSET_BAD ||
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer u->gc_marker == gc_marker + GC_OFFSET_IN_PATH)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (u->in_cleanup_queue)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto bad;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (unit_check_gc(u))
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto good;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer u->gc_marker = gc_marker + GC_OFFSET_IN_PATH;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer is_bad = true;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SET_FOREACH(other, u->dependencies[UNIT_REFERENCED_BY], i) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer unit_gc_sweep(other, gc_marker);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (other->gc_marker == gc_marker + GC_OFFSET_GOOD)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto good;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (other->gc_marker != gc_marker + GC_OFFSET_BAD)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer is_bad = false;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (is_bad)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto bad;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* We were unable to find anything out about this entry, so
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * let's investigate it later */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer u->gc_marker = gc_marker + GC_OFFSET_UNSURE;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer unit_add_to_gc_queue(u);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerbad:
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* We definitely know that this one is not useful anymore, so
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * let's mark it for deletion */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer u->gc_marker = gc_marker + GC_OFFSET_BAD;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer unit_add_to_cleanup_queue(u);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyergood:
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer u->gc_marker = gc_marker + GC_OFFSET_GOOD;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerstatic unsigned manager_dispatch_gc_queue(Manager *m) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer Unit *u;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer unsigned n = 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer unsigned gc_marker;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* log_debug("Running GC..."); */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer m->gc_marker += _GC_OFFSET_MAX;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (m->gc_marker + _GC_OFFSET_MAX <= _GC_OFFSET_MAX)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer m->gc_marker = 1;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer gc_marker = m->gc_marker;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer while ((u = m->gc_queue)) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(u->in_gc_queue);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer unit_gc_sweep(u, gc_marker);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer LIST_REMOVE(gc_queue, m->gc_queue, u);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer u->in_gc_queue = false;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer n++;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (u->gc_marker == gc_marker + GC_OFFSET_BAD ||
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer u->gc_marker == gc_marker + GC_OFFSET_UNSURE) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_debug_unit(u->id, "Collecting %s", u->id);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer u->gc_marker = gc_marker + GC_OFFSET_BAD;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer unit_add_to_cleanup_queue(u);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer m->n_in_gc_queue = 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return n;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerstatic void manager_clear_jobs_and_units(Manager *m) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer Unit *u;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer while ((u = hashmap_first(m->units)))
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer unit_free(u);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer manager_dispatch_cleanup_queue(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(!m->load_queue);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(!m->run_queue);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(!m->dbus_unit_queue);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(!m->dbus_job_queue);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(!m->cleanup_queue);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(!m->gc_queue);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(hashmap_isempty(m->jobs));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(hashmap_isempty(m->units));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer m->n_on_console = 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer m->n_running_jobs = 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyervoid manager_free(Manager *m) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer UnitType c;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer int i;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer manager_clear_jobs_and_units(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer for (c = 0; c < _UNIT_TYPE_MAX; c++)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (unit_vtable[c]->shutdown)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer unit_vtable[c]->shutdown(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* If we reexecute ourselves, we keep the root cgroup
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * around */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer manager_shutdown_cgroup(m, m->exit_code != MANAGER_REEXECUTE);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer manager_undo_generators(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer bus_done(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer hashmap_free(m->units);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer hashmap_free(m->jobs);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer hashmap_free(m->watch_pids);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer hashmap_free(m->watch_bus);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer sd_event_source_unref(m->signal_event_source);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer sd_event_source_unref(m->notify_event_source);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer sd_event_source_unref(m->time_change_event_source);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer sd_event_source_unref(m->jobs_in_progress_event_source);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer sd_event_source_unref(m->idle_pipe_event_source);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer sd_event_source_unref(m->run_queue_event_source);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (m->signal_fd >= 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer close_nointr_nofail(m->signal_fd);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (m->notify_fd >= 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer close_nointr_nofail(m->notify_fd);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (m->time_change_fd >= 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer close_nointr_nofail(m->time_change_fd);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (m->kdbus_fd >= 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer close_nointr_nofail(m->kdbus_fd);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer manager_close_idle_pipe(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer udev_unref(m->udev);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer sd_event_unref(m->event);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer free(m->notify_socket);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer lookup_paths_free(&m->lookup_paths);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer strv_free(m->environment);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer hashmap_free(m->cgroup_unit);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer set_free_free(m->unit_path_cache);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer free(m->switch_root);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer free(m->switch_root_init);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer for (i = 0; i < RLIMIT_NLIMITS; i++)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer free(m->rlimit[i]);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(hashmap_isempty(m->units_requiring_mounts_for));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer hashmap_free(m->units_requiring_mounts_for);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer free(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerint manager_enumerate(Manager *m) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer int r = 0, q;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer UnitType c;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* Let's ask every type to load all units from disk/kernel
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * that it might know */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer for (c = 0; c < _UNIT_TYPE_MAX; c++)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (unit_vtable[c]->enumerate) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer q = unit_vtable[c]->enumerate(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (q < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = q;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer manager_dispatch_load_queue(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerstatic int manager_coldplug(Manager *m) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer int r = 0, q;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer Iterator i;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer Unit *u;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer char *k;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* Then, let's set up their initial state. */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer HASHMAP_FOREACH_KEY(u, k, m->units, i) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* ignore aliases */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (u->id != k)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer continue;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if ((q = unit_coldplug(u)) < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = q;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerstatic void manager_build_unit_path_cache(Manager *m) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer char **i;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer _cleanup_free_ DIR *d = NULL;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer int r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer set_free_free(m->unit_path_cache);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer m->unit_path_cache = set_new(string_hash_func, string_compare_func);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (!m->unit_path_cache) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_error("Failed to allocate unit path cache.");
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* This simply builds a list of files we know exist, so that
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * we don't always have to go to disk */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer STRV_FOREACH(i, m->lookup_paths.unit_path) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer struct dirent *de;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer d = opendir(*i);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (!d) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (errno != ENOENT)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_error("Failed to open directory %s: %m", *i);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer continue;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer while ((de = readdir(d))) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer char *p;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (ignore_file(de->d_name))
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer continue;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer p = strjoin(streq(*i, "/") ? "" : *i, "/", de->d_name, NULL);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (!p) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = -ENOMEM;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto fail;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = set_consume(m->unit_path_cache, p);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto fail;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer closedir(d);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer d = NULL;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerfail:
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_error("Failed to build unit path cache: %s", strerror(-r));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer set_free_free(m->unit_path_cache);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer m->unit_path_cache = NULL;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyerstatic int manager_distribute_fds(Manager *m, FDSet *fds) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer Unit *u;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer Iterator i;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer int r;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer assert(m);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer HASHMAP_FOREACH(u, m->units, i) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (fdset_size(fds) <= 0)
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer break;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (UNIT_VTABLE(u)->distribute_fds) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer r = UNIT_VTABLE(u)->distribute_fds(u, fds);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (r < 0)
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer return r;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer }
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer }
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer return 0;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer}
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyerint manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer int r, q;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer assert(m);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer dual_timestamp_get(&m->generators_start_timestamp);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer manager_run_generators(m);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer dual_timestamp_get(&m->generators_finish_timestamp);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer r = lookup_paths_init(
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer &m->lookup_paths, m->running_as, true,
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer m->generator_unit_path,
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer m->generator_unit_path_early,
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer m->generator_unit_path_late);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (r < 0)
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer return r;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer manager_build_unit_path_cache(m);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer /* If we will deserialize make sure that during enumeration
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer * this is already known, so we increase the counter here
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer * already */
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (serialization)
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer m->n_reloading ++;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer /* First, enumerate what we can from all config files */
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer dual_timestamp_get(&m->units_load_start_timestamp);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer r = manager_enumerate(m);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer dual_timestamp_get(&m->units_load_finish_timestamp);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer /* Second, deserialize if there is something to deserialize */
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (serialization) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer q = manager_deserialize(m, serialization, fds);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (q < 0)
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer r = q;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer }
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer /* Any fds left? Find some unit which wants them. This is
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer * useful to allow container managers to pass some file
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer * descriptors to us pre-initialized. This enables
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer * socket-based activation of entire containers. */
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (fdset_size(fds) > 0) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer q = manager_distribute_fds(m, fds);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (q < 0)
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer r = q;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer }
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer /* We might have deserialized the kdbus control fd, but if we
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer * didn't, then let's create the bus now. */
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer manager_setup_kdbus(m);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer manager_connect_bus(m, !!serialization);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer /* Third, fire things up! */
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer q = manager_coldplug(m);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (q < 0)
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer r = q;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
c53158818d8cdaf46b3f1b5299b9bda118a1043fThomas Hindoe Paaboel Andersen if (serialization) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer assert(m->n_reloading > 0);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer m->n_reloading --;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer /* Let's wait for the UnitNew/JobNew messages being
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer * sent, before we notify that the reload is
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer * finished */
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer m->send_reloading_done = true;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer }
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer return r;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer}
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyerint manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool override, sd_bus_error *e, Job **_ret) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer int r;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer Transaction *tr;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer assert(m);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer assert(type < _JOB_TYPE_MAX);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer assert(unit);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer assert(mode < _JOB_MODE_MAX);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (mode == JOB_ISOLATE && type != JOB_START) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Isolate is only valid for start.");
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer return -EINVAL;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer }
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (mode == JOB_ISOLATE && !unit->allow_isolate) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer sd_bus_error_setf(e, BUS_ERROR_NO_ISOLATION, "Operation refused, unit may not be isolated.");
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer return -EPERM;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer }
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer log_debug_unit(unit->id,
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer "Trying to enqueue job %s/%s/%s", unit->id,
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer job_type_to_string(type), job_mode_to_string(mode));
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer job_type_collapse(&type, unit);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer tr = transaction_new(mode == JOB_REPLACE_IRREVERSIBLY);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (!tr)
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer return -ENOMEM;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer r = transaction_add_job_and_dependencies(tr, type, unit, NULL, true, override, false,
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer mode == JOB_IGNORE_DEPENDENCIES || mode == JOB_IGNORE_REQUIREMENTS,
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer mode == JOB_IGNORE_DEPENDENCIES, e);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (r < 0)
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer goto tr_abort;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (mode == JOB_ISOLATE) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer r = transaction_add_isolate_jobs(tr, m);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (r < 0)
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer goto tr_abort;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer }
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer r = transaction_activate(tr, m, mode, e);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (r < 0)
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer goto tr_abort;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer log_debug_unit(unit->id,
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer "Enqueued job %s/%s as %u", unit->id,
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer job_type_to_string(type), (unsigned) tr->anchor_job->id);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (_ret)
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer *_ret = tr->anchor_job;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer transaction_free(tr);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer return 0;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyertr_abort:
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer transaction_abort(tr);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer transaction_free(tr);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer return r;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer}
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyerint manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, bool override, sd_bus_error *e, Job **_ret) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer Unit *unit;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer int r;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer assert(m);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer assert(type < _JOB_TYPE_MAX);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer assert(name);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer assert(mode < _JOB_MODE_MAX);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer r = manager_load_unit(m, name, NULL, NULL, &unit);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (r < 0)
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer return r;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer return manager_add_job(m, type, unit, mode, override, e, _ret);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer}
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald HoyerJob *manager_get_job(Manager *m, uint32_t id) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer assert(m);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer return hashmap_get(m->jobs, UINT32_TO_PTR(id));
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer}
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald HoyerUnit *manager_get_unit(Manager *m, const char *name) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer assert(m);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer assert(name);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer return hashmap_get(m->units, name);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer}
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyerunsigned manager_dispatch_load_queue(Manager *m) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer Unit *u;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer unsigned n = 0;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer assert(m);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer /* Make sure we are not run recursively */
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (m->dispatching_load_queue)
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer return 0;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer m->dispatching_load_queue = true;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer /* Dispatches the load queue. Takes a unit from the queue and
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer * tries to load its data until the queue is empty */
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer while ((u = m->load_queue)) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer assert(u->in_load_queue);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer unit_load(u);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer n++;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer }
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer m->dispatching_load_queue = false;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer return n;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer}
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyerint manager_load_unit_prepare(
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer Manager *m,
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer const char *name,
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer const char *path,
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer sd_bus_error *e,
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer Unit **_ret) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer Unit *ret;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer UnitType t;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer int r;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer assert(m);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer assert(name || path);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* This will prepare the unit for loading, but not actually
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * load anything from disk. */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (path && !is_path(path))
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (!name)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer name = basename(path);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer t = unit_name_to_type(name);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (t == _UNIT_TYPE_INVALID || !unit_name_is_valid(name, false))
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s is not valid.", name);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer ret = manager_get_unit(m, name);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (ret) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer *_ret = ret;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return 1;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer ret = unit_new(m, unit_vtable[t]->object_size);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (!ret)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return -ENOMEM;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (path) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer ret->fragment_path = strdup(path);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (!ret->fragment_path) {
1ecf6a2b4960229ad1d06c591b4776ddf065e834Harald Hoyer unit_free(ret);
1ecf6a2b4960229ad1d06c591b4776ddf065e834Harald Hoyer return -ENOMEM;
1ecf6a2b4960229ad1d06c591b4776ddf065e834Harald Hoyer }
1ecf6a2b4960229ad1d06c591b4776ddf065e834Harald Hoyer }
1ecf6a2b4960229ad1d06c591b4776ddf065e834Harald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = unit_add_name(ret, name);
33a5e20ffaa2cbb2853f14265566bac66a7f9026Harald Hoyer if (r < 0) {
33a5e20ffaa2cbb2853f14265566bac66a7f9026Harald Hoyer unit_free(ret);
33a5e20ffaa2cbb2853f14265566bac66a7f9026Harald Hoyer return r;
33a5e20ffaa2cbb2853f14265566bac66a7f9026Harald Hoyer }
33a5e20ffaa2cbb2853f14265566bac66a7f9026Harald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer unit_add_to_load_queue(ret);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer unit_add_to_dbus_queue(ret);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer unit_add_to_gc_queue(ret);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (_ret)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer *_ret = ret;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierint manager_load_unit(
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer Manager *m,
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer const char *name,
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer const char *path,
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer sd_bus_error *e,
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer Unit **_ret) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer int r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* This will load the service information files, but not actually
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * start any services or anything. */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = manager_load_unit_prepare(m, name, path, e, _ret);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r != 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer manager_dispatch_load_queue(m);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (_ret)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer *_ret = unit_follow_merge(*_ret);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyervoid manager_dump_jobs(Manager *s, FILE *f, const char *prefix) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer Iterator i;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer Job *j;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(s);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(f);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer HASHMAP_FOREACH(j, s->jobs, i)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer job_dump(j, f, prefix);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyervoid manager_dump_units(Manager *s, FILE *f, const char *prefix) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer Iterator i;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer Unit *u;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer const char *t;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(s);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(f);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer HASHMAP_FOREACH_KEY(u, t, s->units, i)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (u->id == t)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer unit_dump(u, f, prefix);
}
void manager_clear_jobs(Manager *m) {
Job *j;
assert(m);
while ((j = hashmap_first(m->jobs)))
/* No need to recurse. We're cancelling all jobs. */
job_finish_and_invalidate(j, JOB_CANCELED, false);
}
static int manager_dispatch_run_queue(sd_event_source *source, void *userdata) {
Manager *m = userdata;
Job *j;
assert(source);
assert(m);
while ((j = m->run_queue)) {
assert(j->installed);
assert(j->in_run_queue);
job_run_and_invalidate(j);
}
if (m->n_running_jobs > 0)
manager_watch_jobs_in_progress(m);
if (m->n_on_console > 0)
manager_watch_idle_pipe(m);
return 1;
}
static unsigned manager_dispatch_dbus_queue(Manager *m) {
Job *j;
Unit *u;
unsigned n = 0;
assert(m);
if (m->dispatching_dbus_queue)
return 0;
m->dispatching_dbus_queue = true;
while ((u = m->dbus_unit_queue)) {
assert(u->in_dbus_queue);
bus_unit_send_change_signal(u);
n++;
}
while ((j = m->dbus_job_queue)) {
assert(j->in_dbus_queue);
bus_job_send_change_signal(j);
n++;
}
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)
bus_send_queued_message(m);
return n;
}
static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
Manager *m = userdata;
ssize_t n;
assert(m);
assert(m->notify_fd == fd);
if (revents != EPOLLIN) {
log_warning("Got unexpected poll event for notify fd.");
return 0;
}
for (;;) {
char buf[4096];
struct iovec iovec = {
.iov_base = buf,
.iov_len = sizeof(buf)-1,
};
union {
struct cmsghdr cmsghdr;
uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
} control = {};
struct msghdr msghdr = {
.msg_iov = &iovec,
.msg_iovlen = 1,
.msg_control = &control,
.msg_controllen = sizeof(control),
};
struct ucred *ucred;
Unit *u;
_cleanup_strv_free_ char **tags = NULL;
n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT);
if (n <= 0) {
if (n == 0)
return -EIO;
if (errno == EAGAIN || errno == EINTR)
break;
return -errno;
}
if (msghdr.msg_controllen < CMSG_LEN(sizeof(struct ucred)) ||
control.cmsghdr.cmsg_level != SOL_SOCKET ||
control.cmsghdr.cmsg_type != SCM_CREDENTIALS ||
control.cmsghdr.cmsg_len != CMSG_LEN(sizeof(struct ucred))) {
log_warning("Received notify message without credentials. Ignoring.");
continue;
}
ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr);
u = hashmap_get(m->watch_pids, LONG_TO_PTR(ucred->pid));
if (!u) {
u = manager_get_unit_by_pid(m, ucred->pid);
if (!u) {
log_warning("Cannot find unit for notify message of PID %lu.", (unsigned long) ucred->pid);
continue;
}
}
assert((size_t) n < sizeof(buf));
buf[n] = 0;
tags = strv_split(buf, "\n\r");
if (!tags)
return log_oom();
log_debug_unit(u->id, "Got notification message for unit %s", u->id);
if (UNIT_VTABLE(u)->notify_message)
UNIT_VTABLE(u)->notify_message(u, ucred->pid, tags);
}
return 0;
}
static int manager_dispatch_sigchld(Manager *m) {
assert(m);
for (;;) {
siginfo_t si = {};
Unit *u;
int r;
/* First we call waitd() for a PID and do not reap the
* zombie. That way we can still access /proc/$PID for
* it while it is a zombie. */
if (waitid(P_ALL, 0, &si, WEXITED|WNOHANG|WNOWAIT) < 0) {
if (errno == ECHILD)
break;
if (errno == EINTR)
continue;
return -errno;
}
if (si.si_pid <= 0)
break;
if (si.si_code == CLD_EXITED || si.si_code == CLD_KILLED || si.si_code == CLD_DUMPED) {
_cleanup_free_ char *name = NULL;
get_process_comm(si.si_pid, &name);
log_debug("Got SIGCHLD for process %lu (%s)", (unsigned long) si.si_pid, strna(name));
}
/* Let's flush any message the dying child might still
* have queued for us. This ensures that the process
* still exists in /proc so that we can figure out
* which cgroup and hence unit it belongs to. */
r = manager_dispatch_notify_fd(m->notify_event_source, m->notify_fd, EPOLLIN, m);
if (r < 0)
return r;
/* And now figure out the unit this belongs to */
u = hashmap_get(m->watch_pids, LONG_TO_PTR(si.si_pid));
if (!u)
u = manager_get_unit_by_pid(m, si.si_pid);
/* And now, we actually reap the zombie. */
if (waitid(P_PID, si.si_pid, &si, WEXITED) < 0) {
if (errno == EINTR)
continue;
return -errno;
}
if (si.si_code != CLD_EXITED && si.si_code != CLD_KILLED && si.si_code != CLD_DUMPED)
continue;
log_debug("Child %lu died (code=%s, status=%i/%s)",
(long unsigned) si.si_pid,
sigchld_code_to_string(si.si_code),
si.si_status,
strna(si.si_code == CLD_EXITED
? exit_status_to_string(si.si_status, EXIT_STATUS_FULL)
: signal_to_string(si.si_status)));
if (!u)
continue;
log_debug_unit(u->id,
"Child %lu belongs to %s", (long unsigned) si.si_pid, u->id);
hashmap_remove(m->watch_pids, LONG_TO_PTR(si.si_pid));
UNIT_VTABLE(u)->sigchld_event(u, si.si_pid, si.si_code, si.si_status);
}
return 0;
}
static int manager_start_target(Manager *m, const char *name, JobMode mode) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
log_debug_unit(name, "Activating special unit %s", name);
r = manager_add_job_by_name(m, JOB_START, name, mode, true, &error, NULL);
if (r < 0)
log_error_unit(name, "Failed to enqueue %s job: %s", name, bus_error_message(&error, r));
return r;
}
static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
Manager *m = userdata;
ssize_t n;
struct signalfd_siginfo sfsi;
bool sigchld = false;
assert(m);
assert(m->signal_fd == fd);
if (revents != EPOLLIN) {
log_warning("Got unexpected events from signal file descriptor.");
return 0;
}
for (;;) {
n = read(m->signal_fd, &sfsi, sizeof(sfsi));
if (n != sizeof(sfsi)) {
if (n >= 0)
return -EIO;
if (errno == EINTR || errno == EAGAIN)
break;
return -errno;
}
if (sfsi.ssi_pid > 0) {
char *p = NULL;
get_process_comm(sfsi.ssi_pid, &p);
log_debug("Received SIG%s from PID %lu (%s).",
signal_to_string(sfsi.ssi_signo),
(unsigned long) sfsi.ssi_pid, strna(p));
free(p);
} else
log_debug("Received SIG%s.", signal_to_string(sfsi.ssi_signo));
switch (sfsi.ssi_signo) {
case SIGCHLD:
sigchld = true;
break;
case SIGTERM:
if (m->running_as == SYSTEMD_SYSTEM) {
/* This is for compatibility with the
* original sysvinit */
m->exit_code = MANAGER_REEXECUTE;
break;
}
/* Fall through */
case SIGINT:
if (m->running_as == SYSTEMD_SYSTEM) {
manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE_IRREVERSIBLY);
break;
}
/* Run the exit target if there is one, if not, just exit. */
if (manager_start_target(m, SPECIAL_EXIT_TARGET, JOB_REPLACE) < 0) {
m->exit_code = MANAGER_EXIT;
return 0;
}
break;
case SIGWINCH:
if (m->running_as == SYSTEMD_SYSTEM)
manager_start_target(m, SPECIAL_KBREQUEST_TARGET, JOB_REPLACE);
/* This is a nop on non-init */
break;
case SIGPWR:
if (m->running_as == SYSTEMD_SYSTEM)
manager_start_target(m, SPECIAL_SIGPWR_TARGET, JOB_REPLACE);
/* This is a nop on non-init */
break;
case SIGUSR1: {
Unit *u;
u = manager_get_unit(m, SPECIAL_DBUS_SERVICE);
if (!u || UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) {
log_info("Trying to reconnect to bus...");
bus_init(m, true);
}
if (!u || !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u))) {
log_info("Loading D-Bus service...");
manager_start_target(m, SPECIAL_DBUS_SERVICE, JOB_REPLACE);
}
break;
}
case SIGUSR2: {
_cleanup_free_ char *dump = NULL;
_cleanup_fclose_ FILE *f = NULL;
size_t size;
f = open_memstream(&dump, &size);
if (!f) {
log_warning("Failed to allocate memory stream.");
break;
}
manager_dump_units(m, f, "\t");
manager_dump_jobs(m, f, "\t");
if (ferror(f)) {
log_warning("Failed to write status stream");
break;
}
log_dump(LOG_INFO, dump);
break;
}
case SIGHUP:
m->exit_code = MANAGER_RELOAD;
break;
default: {
/* Starting SIGRTMIN+0 */
static const char * const target_table[] = {
[0] = SPECIAL_DEFAULT_TARGET,
[1] = SPECIAL_RESCUE_TARGET,
[2] = SPECIAL_EMERGENCY_TARGET,
[3] = SPECIAL_HALT_TARGET,
[4] = SPECIAL_POWEROFF_TARGET,
[5] = SPECIAL_REBOOT_TARGET,
[6] = SPECIAL_KEXEC_TARGET
};
/* Starting SIGRTMIN+13, so that target halt and system halt are 10 apart */
static const ManagerExitCode code_table[] = {
[0] = MANAGER_HALT,
[1] = MANAGER_POWEROFF,
[2] = MANAGER_REBOOT,
[3] = MANAGER_KEXEC
};
if ((int) sfsi.ssi_signo >= SIGRTMIN+0 &&
(int) sfsi.ssi_signo < SIGRTMIN+(int) ELEMENTSOF(target_table)) {
int idx = (int) sfsi.ssi_signo - SIGRTMIN;
manager_start_target(m, target_table[idx],
(idx == 1 || idx == 2) ? JOB_ISOLATE : JOB_REPLACE);
break;
}
if ((int) sfsi.ssi_signo >= SIGRTMIN+13 &&
(int) sfsi.ssi_signo < SIGRTMIN+13+(int) ELEMENTSOF(code_table)) {
m->exit_code = code_table[sfsi.ssi_signo - SIGRTMIN - 13];
break;
}
switch (sfsi.ssi_signo - SIGRTMIN) {
case 20:
log_debug("Enabling showing of status.");
manager_set_show_status(m, true);
break;
case 21:
log_debug("Disabling showing of status.");
manager_set_show_status(m, false);
break;
case 22:
log_set_max_level(LOG_DEBUG);
log_notice("Setting log level to debug.");
break;
case 23:
log_set_max_level(LOG_INFO);
log_notice("Setting log level to info.");
break;
case 24:
if (m->running_as == SYSTEMD_USER) {
m->exit_code = MANAGER_EXIT;
return 0;
}
/* This is a nop on init */
break;
case 26:
log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
log_notice("Setting log target to journal-or-kmsg.");
break;
case 27:
log_set_target(LOG_TARGET_CONSOLE);
log_notice("Setting log target to console.");
break;
case 28:
log_set_target(LOG_TARGET_KMSG);
log_notice("Setting log target to kmsg.");
break;
case 29:
log_set_target(LOG_TARGET_SYSLOG_OR_KMSG);
log_notice("Setting log target to syslog-or-kmsg.");
break;
default:
log_warning("Got unhandled signal <%s>.", signal_to_string(sfsi.ssi_signo));
}
}
}
}
if (sigchld)
return manager_dispatch_sigchld(m);
return 0;
}
static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
Manager *m = userdata;
Iterator i;
Unit *u;
assert(m);
assert(m->time_change_fd == fd);
log_struct(LOG_INFO,
MESSAGE_ID(SD_MESSAGE_TIME_CHANGE),
"MESSAGE=Time has been changed",
NULL);
/* Restart the watch */
m->time_change_event_source = sd_event_source_unref(m->time_change_event_source);
close_nointr_nofail(m->time_change_fd);
m->time_change_fd = -1;
manager_setup_time_change(m);
HASHMAP_FOREACH(u, m->units, i)
if (UNIT_VTABLE(u)->time_change)
UNIT_VTABLE(u)->time_change(u);
return 0;
}
static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
Manager *m = userdata;
assert(m);
assert(m->idle_pipe[2] == fd);
m->no_console_output = m->n_on_console > 0;
m->idle_pipe_event_source = sd_event_source_unref(m->idle_pipe_event_source);
manager_close_idle_pipe(m);
return 0;
}
static int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata) {
Manager *m = userdata;
assert(m);
manager_print_jobs_in_progress(m);
return 0;
}
int manager_loop(Manager *m) {
int r;
RATELIMIT_DEFINE(rl, 1*USEC_PER_SEC, 50000);
assert(m);
m->exit_code = MANAGER_RUNNING;
/* Release the path cache */
set_free_free(m->unit_path_cache);
m->unit_path_cache = NULL;
manager_check_finished(m);
/* There might still be some zombies hanging around from
* before we were exec()'ed. Let's reap them. */
r = manager_dispatch_sigchld(m);
if (r < 0)
return r;
while (m->exit_code == MANAGER_RUNNING) {
usec_t wait_usec;
if (m->runtime_watchdog > 0 && m->running_as == SYSTEMD_SYSTEM)
watchdog_ping();
if (!ratelimit_test(&rl)) {
/* Yay, something is going seriously wrong, pause a little */
log_warning("Looping too fast. Throttling execution a little.");
sleep(1);
continue;
}
if (manager_dispatch_load_queue(m) > 0)
continue;
if (manager_dispatch_gc_queue(m) > 0)
continue;
if (manager_dispatch_cleanup_queue(m) > 0)
continue;
if (manager_dispatch_cgroup_queue(m) > 0)
continue;
if (manager_dispatch_dbus_queue(m) > 0)
continue;
/* Sleep for half the watchdog time */
if (m->runtime_watchdog > 0 && m->running_as == SYSTEMD_SYSTEM) {
wait_usec = m->runtime_watchdog / 2;
if (wait_usec <= 0)
wait_usec = 1;
} else
wait_usec = (usec_t) -1;
r = sd_event_run(m->event, wait_usec);
if (r < 0) {
log_error("Failed to run event loop: %s", strerror(-r));
return r;
}
}
return m->exit_code;
}
int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e, Unit **_u) {
_cleanup_free_ char *n = NULL;
Unit *u;
int r;
assert(m);
assert(s);
assert(_u);
r = unit_name_from_dbus_path(s, &n);
if (r < 0)
return r;
r = manager_load_unit(m, n, NULL, e, &u);
if (r < 0)
return r;
*_u = u;
return 0;
}
int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j) {
const char *p;
unsigned id;
Job *j;
int r;
assert(m);
assert(s);
assert(_j);
p = startswith(s, "/org/freedesktop/systemd1/job/");
if (!p)
return -EINVAL;
r = safe_atou(p, &id);
if (r < 0)
return r;
j = manager_get_job(m, id);
if (!j)
return -ENOENT;
*_j = j;
return 0;
}
void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) {
#ifdef HAVE_AUDIT
char *p;
int audit_fd;
audit_fd = get_audit_fd();
if (audit_fd < 0)
return;
/* Don't generate audit events if the service was already
* started and we're just deserializing */
if (m->n_reloading > 0)
return;
if (m->running_as != SYSTEMD_SYSTEM)
return;
if (u->type != UNIT_SERVICE)
return;
p = unit_name_to_prefix_and_instance(u->id);
if (!p) {
log_error_unit(u->id,
"Failed to allocate unit name for audit message: %s", strerror(ENOMEM));
return;
}
if (audit_log_user_comm_message(audit_fd, type, "", p, NULL, NULL, NULL, success) < 0) {
if (errno == EPERM) {
/* We aren't allowed to send audit messages?
* Then let's not retry again. */
close_audit_fd();
} else
log_warning("Failed to send audit message: %m");
}
free(p);
#endif
}
void manager_send_unit_plymouth(Manager *m, Unit *u) {
int fd = -1;
union sockaddr_union sa;
int n = 0;
char *message = NULL;
/* Don't generate plymouth events if the service was already
* started and we're just deserializing */
if (m->n_reloading > 0)
return;
if (m->running_as != SYSTEMD_SYSTEM)
return;
if (detect_container(NULL) > 0)
return;
if (u->type != UNIT_SERVICE &&
u->type != UNIT_MOUNT &&
u->type != UNIT_SWAP)
return;
/* We set SOCK_NONBLOCK here so that we rather drop the
* message then wait for plymouth */
fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (fd < 0) {
log_error("socket() failed: %m");
return;
}
zero(sa);
sa.sa.sa_family = AF_UNIX;
strncpy(sa.un.sun_path+1, "/org/freedesktop/plymouthd", sizeof(sa.un.sun_path)-1);
if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) {
if (errno != EPIPE &&
errno != EAGAIN &&
errno != ENOENT &&
errno != ECONNREFUSED &&
errno != ECONNRESET &&
errno != ECONNABORTED)
log_error("connect() failed: %m");
goto finish;
}
if (asprintf(&message, "U\002%c%s%n", (int) (strlen(u->id) + 1), u->id, &n) < 0) {
log_oom();
goto finish;
}
errno = 0;
if (write(fd, message, n + 1) != n + 1) {
if (errno != EPIPE &&
errno != EAGAIN &&
errno != ENOENT &&
errno != ECONNREFUSED &&
errno != ECONNRESET &&
errno != ECONNABORTED)
log_error("Failed to write Plymouth message: %m");
goto finish;
}
finish:
if (fd >= 0)
close_nointr_nofail(fd);
free(message);
}
void manager_dispatch_bus_name_owner_changed(
Manager *m,
const char *name,
const char* old_owner,
const char *new_owner) {
Unit *u;
assert(m);
assert(name);
u = hashmap_get(m->watch_bus, name);
if (!u)
return;
UNIT_VTABLE(u)->bus_name_owner_change(u, name, old_owner, new_owner);
}
int manager_open_serialization(Manager *m, FILE **_f) {
char *path = NULL;
int fd = -1;
FILE *f;
assert(_f);
if (m->running_as == SYSTEMD_SYSTEM)
asprintf(&path, "/run/systemd/dump-%lu-XXXXXX", (unsigned long) getpid());
else
asprintf(&path, "/tmp/systemd-dump-%lu-XXXXXX", (unsigned long) getpid());
if (!path)
return -ENOMEM;
RUN_WITH_UMASK(0077) {
fd = mkostemp(path, O_RDWR|O_CLOEXEC);
}
if (fd < 0) {
free(path);
return -errno;
}
unlink(path);
log_debug("Serializing state to %s", path);
free(path);
f = fdopen(fd, "w+");
if (!f)
return -errno;
*_f = f;
return 0;
}
int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) {
Iterator i;
Unit *u;
const char *t;
char **e;
int r;
assert(m);
assert(f);
assert(fds);
m->n_reloading ++;
fprintf(f, "current-job-id=%i\n", m->current_job_id);
fprintf(f, "taint-usr=%s\n", yes_no(m->taint_usr));
fprintf(f, "n-installed-jobs=%u\n", m->n_installed_jobs);
fprintf(f, "n-failed-jobs=%u\n", m->n_failed_jobs);
dual_timestamp_serialize(f, "firmware-timestamp", &m->firmware_timestamp);
dual_timestamp_serialize(f, "loader-timestamp", &m->loader_timestamp);
dual_timestamp_serialize(f, "kernel-timestamp", &m->kernel_timestamp);
dual_timestamp_serialize(f, "initrd-timestamp", &m->initrd_timestamp);
if (!in_initrd()) {
dual_timestamp_serialize(f, "userspace-timestamp", &m->userspace_timestamp);
dual_timestamp_serialize(f, "finish-timestamp", &m->finish_timestamp);
dual_timestamp_serialize(f, "security-start-timestamp", &m->security_start_timestamp);
dual_timestamp_serialize(f, "security-finish-timestamp", &m->security_finish_timestamp);
dual_timestamp_serialize(f, "generators-start-timestamp", &m->generators_start_timestamp);
dual_timestamp_serialize(f, "generators-finish-timestamp", &m->generators_finish_timestamp);
dual_timestamp_serialize(f, "units-load-start-timestamp", &m->units_load_start_timestamp);
dual_timestamp_serialize(f, "units-load-finish-timestamp", &m->units_load_finish_timestamp);
}
if (!switching_root) {
STRV_FOREACH(e, m->environment) {
_cleanup_free_ char *ce;
ce = cescape(*e);
if (!ce)
return -ENOMEM;
fprintf(f, "env=%s\n", *e);
}
}
if (m->kdbus_fd >= 0) {
int copy;
copy = fdset_put_dup(fds, m->kdbus_fd);
if (copy < 0)
return copy;
fprintf(f, "kdbus-fd=%i\n", copy);
}
bus_serialize(m, f);
fputc('\n', f);
HASHMAP_FOREACH_KEY(u, t, m->units, i) {
if (u->id != t)
continue;
if (!unit_can_serialize(u))
continue;
/* Start marker */
fputs(u->id, f);
fputc('\n', f);
r = unit_serialize(u, f, fds, !switching_root);
if (r < 0) {
m->n_reloading --;
return r;
}
}
assert(m->n_reloading > 0);
m->n_reloading --;
if (ferror(f))
return -EIO;
r = bus_fdset_add_all(m, fds);
if (r < 0)
return r;
return 0;
}
int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
int r = 0;
assert(m);
assert(f);
log_debug("Deserializing state...");
m->n_reloading ++;
for (;;) {
char line[LINE_MAX], *l;
if (!fgets(line, sizeof(line), f)) {
if (feof(f))
r = 0;
else
r = -errno;
goto finish;
}
char_array_0(line);
l = strstrip(line);
if (l[0] == 0)
break;
if (startswith(l, "current-job-id=")) {
uint32_t id;
if (safe_atou32(l+15, &id) < 0)
log_debug("Failed to parse current job id value %s", l+15);
else
m->current_job_id = MAX(m->current_job_id, id);
} else if (startswith(l, "n-installed-jobs=")) {
uint32_t n;
if (safe_atou32(l+17, &n) < 0)
log_debug("Failed to parse installed jobs counter %s", l+17);
else
m->n_installed_jobs += n;
} else if (startswith(l, "n-failed-jobs=")) {
uint32_t n;
if (safe_atou32(l+14, &n) < 0)
log_debug("Failed to parse failed jobs counter %s", l+14);
else
m->n_failed_jobs += n;
} else if (startswith(l, "taint-usr=")) {
int b;
b = parse_boolean(l+10);
if (b < 0)
log_debug("Failed to parse taint /usr flag %s", l+10);
else
m->taint_usr = m->taint_usr || b;
} else if (startswith(l, "firmware-timestamp="))
dual_timestamp_deserialize(l+19, &m->firmware_timestamp);
else if (startswith(l, "loader-timestamp="))
dual_timestamp_deserialize(l+17, &m->loader_timestamp);
else if (startswith(l, "kernel-timestamp="))
dual_timestamp_deserialize(l+17, &m->kernel_timestamp);
else if (startswith(l, "initrd-timestamp="))
dual_timestamp_deserialize(l+17, &m->initrd_timestamp);
else if (startswith(l, "userspace-timestamp="))
dual_timestamp_deserialize(l+20, &m->userspace_timestamp);
else if (startswith(l, "finish-timestamp="))
dual_timestamp_deserialize(l+17, &m->finish_timestamp);
else if (startswith(l, "security-start-timestamp="))
dual_timestamp_deserialize(l+25, &m->security_start_timestamp);
else if (startswith(l, "security-finish-timestamp="))
dual_timestamp_deserialize(l+26, &m->security_finish_timestamp);
else if (startswith(l, "generators-start-timestamp="))
dual_timestamp_deserialize(l+27, &m->generators_start_timestamp);
else if (startswith(l, "generators-finish-timestamp="))
dual_timestamp_deserialize(l+28, &m->generators_finish_timestamp);
else if (startswith(l, "units-load-start-timestamp="))
dual_timestamp_deserialize(l+27, &m->units_load_start_timestamp);
else if (startswith(l, "units-load-finish-timestamp="))
dual_timestamp_deserialize(l+28, &m->units_load_finish_timestamp);
else if (startswith(l, "env=")) {
_cleanup_free_ char *uce = NULL;
char **e;
uce = cunescape(l+4);
if (!uce) {
r = -ENOMEM;
goto finish;
}
e = strv_env_set(m->environment, uce);
if (!e) {
r = -ENOMEM;
goto finish;
}
strv_free(m->environment);
m->environment = e;
} else if (startswith(l, "kdbus-fd=")) {
int fd;
if (safe_atoi(l + 9, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
log_debug("Failed to parse kdbus fd: %s", l + 9);
else {
if (m->kdbus_fd >= 0)
close_nointr_nofail(m->kdbus_fd);
m->kdbus_fd = fdset_remove(fds, fd);
}
} else if (bus_deserialize_item(m, l) == 0)
log_debug("Unknown serialization item '%s'", l);
}
for (;;) {
Unit *u;
char name[UNIT_NAME_MAX+2];
/* Start marker */
if (!fgets(name, sizeof(name), f)) {
if (feof(f))
r = 0;
else
r = -errno;
goto finish;
}
char_array_0(name);
r = manager_load_unit(m, strstrip(name), NULL, NULL, &u);
if (r < 0)
goto finish;
r = unit_deserialize(u, f, fds);
if (r < 0)
goto finish;
}
finish:
if (ferror(f))
r = -EIO;
assert(m->n_reloading > 0);
m->n_reloading --;
return r;
}
int manager_reload(Manager *m) {
int r, q;
_cleanup_fclose_ FILE *f = NULL;
_cleanup_fdset_free_ FDSet *fds = NULL;
assert(m);
r = manager_open_serialization(m, &f);
if (r < 0)
return r;
m->n_reloading ++;
bus_manager_send_reloading(m, true);
fds = fdset_new();
if (!fds) {
m->n_reloading --;
return -ENOMEM;
}
r = manager_serialize(m, f, fds, false);
if (r < 0) {
m->n_reloading --;
return r;
}
if (fseeko(f, 0, SEEK_SET) < 0) {
m->n_reloading --;
return -errno;
}
/* From here on there is no way back. */
manager_clear_jobs_and_units(m);
manager_undo_generators(m);
lookup_paths_free(&m->lookup_paths);
/* Find new unit paths */
manager_run_generators(m);
q = lookup_paths_init(
&m->lookup_paths, m->running_as, true,
m->generator_unit_path,
m->generator_unit_path_early,
m->generator_unit_path_late);
if (q < 0)
r = q;
manager_build_unit_path_cache(m);
/* First, enumerate what we can from all config files */
q = manager_enumerate(m);
if (q < 0)
r = q;
/* Second, deserialize our stored data */
q = manager_deserialize(m, f, fds);
if (q < 0)
r = q;
fclose(f);
f = NULL;
/* Third, fire things up! */
q = manager_coldplug(m);
if (q < 0)
r = q;
assert(m->n_reloading > 0);
m->n_reloading--;
m->send_reloading_done = true;
return r;
}
static bool manager_is_booting_or_shutting_down(Manager *m) {
Unit *u;
assert(m);
/* Is the initial job still around? */
if (manager_get_job(m, m->default_unit_job_id))
return true;
/* Is there a job for the shutdown target? */
u = manager_get_unit(m, SPECIAL_SHUTDOWN_TARGET);
if (u)
return !!u->job;
return false;
}
bool manager_is_reloading_or_reexecuting(Manager *m) {
assert(m);
return m->n_reloading != 0;
}
void manager_reset_failed(Manager *m) {
Unit *u;
Iterator i;
assert(m);
HASHMAP_FOREACH(u, m->units, i)
unit_reset_failed(u);
}
bool manager_unit_inactive_or_pending(Manager *m, const char *name) {
Unit *u;
assert(m);
assert(name);
/* Returns true if the unit is inactive or going down */
u = manager_get_unit(m, name);
if (!u)
return true;
return unit_inactive_or_pending(u);
}
void manager_check_finished(Manager *m) {
char userspace[FORMAT_TIMESPAN_MAX], initrd[FORMAT_TIMESPAN_MAX], kernel[FORMAT_TIMESPAN_MAX], sum[FORMAT_TIMESPAN_MAX];
usec_t firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec;
assert(m);
if (m->n_running_jobs == 0)
m->jobs_in_progress_event_source = sd_event_source_unref(m->jobs_in_progress_event_source);
if (hashmap_size(m->jobs) > 0) {
if (m->jobs_in_progress_event_source)
sd_event_source_set_time(m->jobs_in_progress_event_source, JOBS_IN_PROGRESS_PERIOD_SEC);
return;
}
/* Notify Type=idle units that we are done now */
m->idle_pipe_event_source = sd_event_source_unref(m->idle_pipe_event_source);
manager_close_idle_pipe(m);
/* Turn off confirm spawn now */
m->confirm_spawn = false;
if (dual_timestamp_is_set(&m->finish_timestamp))
return;
dual_timestamp_get(&m->finish_timestamp);
if (m->running_as == SYSTEMD_SYSTEM && detect_container(NULL) <= 0) {
/* Note that m->kernel_usec.monotonic is always at 0,
* and m->firmware_usec.monotonic and
* m->loader_usec.monotonic should be considered
* negative values. */
firmware_usec = m->firmware_timestamp.monotonic - m->loader_timestamp.monotonic;
loader_usec = m->loader_timestamp.monotonic - m->kernel_timestamp.monotonic;
userspace_usec = m->finish_timestamp.monotonic - m->userspace_timestamp.monotonic;
total_usec = m->firmware_timestamp.monotonic + m->finish_timestamp.monotonic;
if (dual_timestamp_is_set(&m->initrd_timestamp)) {
kernel_usec = m->initrd_timestamp.monotonic - m->kernel_timestamp.monotonic;
initrd_usec = m->userspace_timestamp.monotonic - m->initrd_timestamp.monotonic;
if (!log_on_console())
log_struct(LOG_INFO,
MESSAGE_ID(SD_MESSAGE_STARTUP_FINISHED),
"KERNEL_USEC=%llu", (unsigned long long) kernel_usec,
"INITRD_USEC=%llu", (unsigned long long) initrd_usec,
"USERSPACE_USEC=%llu", (unsigned long long) userspace_usec,
"MESSAGE=Startup finished in %s (kernel) + %s (initrd) + %s (userspace) = %s.",
format_timespan(kernel, sizeof(kernel), kernel_usec, USEC_PER_MSEC),
format_timespan(initrd, sizeof(initrd), initrd_usec, USEC_PER_MSEC),
format_timespan(userspace, sizeof(userspace), userspace_usec, USEC_PER_MSEC),
format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC),
NULL);
} else {
kernel_usec = m->userspace_timestamp.monotonic - m->kernel_timestamp.monotonic;
initrd_usec = 0;
if (!log_on_console())
log_struct(LOG_INFO,
MESSAGE_ID(SD_MESSAGE_STARTUP_FINISHED),
"KERNEL_USEC=%llu", (unsigned long long) kernel_usec,
"USERSPACE_USEC=%llu", (unsigned long long) userspace_usec,
"MESSAGE=Startup finished in %s (kernel) + %s (userspace) = %s.",
format_timespan(kernel, sizeof(kernel), kernel_usec, USEC_PER_MSEC),
format_timespan(userspace, sizeof(userspace), userspace_usec, USEC_PER_MSEC),
format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC),
NULL);
}
} else {
firmware_usec = loader_usec = initrd_usec = kernel_usec = 0;
total_usec = userspace_usec = m->finish_timestamp.monotonic - m->userspace_timestamp.monotonic;
if (!log_on_console())
log_struct(LOG_INFO,
MESSAGE_ID(SD_MESSAGE_STARTUP_FINISHED),
"USERSPACE_USEC=%llu", (unsigned long long) userspace_usec,
"MESSAGE=Startup finished in %s.",
format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC),
NULL);
}
bus_manager_send_finished(m, firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec);
sd_notifyf(false,
"READY=1\nSTATUS=Startup finished in %s.",
format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC));
}
static int create_generator_dir(Manager *m, char **generator, const char *name) {
char *p;
int r;
assert(m);
assert(generator);
assert(name);
if (*generator)
return 0;
if (m->running_as == SYSTEMD_SYSTEM && getpid() == 1) {
p = strappend("/run/systemd/", name);
if (!p)
return log_oom();
r = mkdir_p_label(p, 0755);
if (r < 0) {
log_error("Failed to create generator directory %s: %s",
p, strerror(-r));
free(p);
return r;
}
} else {
p = strjoin("/tmp/systemd-", name, ".XXXXXX", NULL);
if (!p)
return log_oom();
if (!mkdtemp(p)) {
log_error("Failed to create generator directory %s: %m",
p);
free(p);
return -errno;
}
}
*generator = p;
return 0;
}
static void trim_generator_dir(Manager *m, char **generator) {
assert(m);
assert(generator);
if (!*generator)
return;
if (rmdir(*generator) >= 0) {
free(*generator);
*generator = NULL;
}
return;
}
void manager_run_generators(Manager *m) {
_cleanup_closedir_ DIR *d = NULL;
const char *generator_path;
const char *argv[5];
int r;
assert(m);
generator_path = m->running_as == SYSTEMD_SYSTEM ? SYSTEM_GENERATOR_PATH : USER_GENERATOR_PATH;
d = opendir(generator_path);
if (!d) {
if (errno == ENOENT)
return;
log_error("Failed to enumerate generator directory %s: %m",
generator_path);
return;
}
r = create_generator_dir(m, &m->generator_unit_path, "generator");
if (r < 0)
goto finish;
r = create_generator_dir(m, &m->generator_unit_path_early, "generator.early");
if (r < 0)
goto finish;
r = create_generator_dir(m, &m->generator_unit_path_late, "generator.late");
if (r < 0)
goto finish;
argv[0] = NULL; /* Leave this empty, execute_directory() will fill something in */
argv[1] = m->generator_unit_path;
argv[2] = m->generator_unit_path_early;
argv[3] = m->generator_unit_path_late;
argv[4] = NULL;
RUN_WITH_UMASK(0022)
execute_directory(generator_path, d, (char**) argv);
finish:
trim_generator_dir(m, &m->generator_unit_path);
trim_generator_dir(m, &m->generator_unit_path_early);
trim_generator_dir(m, &m->generator_unit_path_late);
}
static void remove_generator_dir(Manager *m, char **generator) {
assert(m);
assert(generator);
if (!*generator)
return;
strv_remove(m->lookup_paths.unit_path, *generator);
rm_rf(*generator, false, true, false);
free(*generator);
*generator = NULL;
}
void manager_undo_generators(Manager *m) {
assert(m);
remove_generator_dir(m, &m->generator_unit_path);
remove_generator_dir(m, &m->generator_unit_path_early);
remove_generator_dir(m, &m->generator_unit_path_late);
}
int manager_environment_add(Manager *m, char **minus, char **plus) {
char **a = NULL, **b = NULL, **l;
assert(m);
l = m->environment;
if (!strv_isempty(minus)) {
a = strv_env_delete(l, 1, minus);
if (!a)
return -ENOMEM;
l = a;
}
if (!strv_isempty(plus)) {
b = strv_env_merge(2, l, plus);
if (!b)
return -ENOMEM;
l = b;
}
if (m->environment != l)
strv_free(m->environment);
if (a != l)
strv_free(a);
if (b != l)
strv_free(b);
m->environment = strv_sort(l);
return 0;
}
int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit) {
int i;
assert(m);
for (i = 0; i < RLIMIT_NLIMITS; i++) {
if (!default_rlimit[i])
continue;
m->rlimit[i] = newdup(struct rlimit, default_rlimit[i], 1);
if (!m->rlimit[i])
return -ENOMEM;
}
return 0;
}
void manager_recheck_journal(Manager *m) {
Unit *u;
assert(m);
if (m->running_as != SYSTEMD_SYSTEM)
return;
u = manager_get_unit(m, SPECIAL_JOURNALD_SOCKET);
if (u && SOCKET(u)->state != SOCKET_RUNNING) {
log_close_journal();
return;
}
u = manager_get_unit(m, SPECIAL_JOURNALD_SERVICE);
if (u && SERVICE(u)->state != SERVICE_RUNNING) {
log_close_journal();
return;
}
/* Hmm, OK, so the socket is fully up and the service is up
* too, then let's make use of the thing. */
log_open();
}
void manager_set_show_status(Manager *m, bool b) {
assert(m);
if (m->running_as != SYSTEMD_SYSTEM)
return;
m->show_status = b;
if (b)
touch("/run/systemd/show-status");
else
unlink("/run/systemd/show-status");
}
static bool manager_get_show_status(Manager *m) {
assert(m);
if (m->running_as != SYSTEMD_SYSTEM)
return false;
if (m->no_console_output)
return false;
if (m->show_status)
return true;
/* If Plymouth is running make sure we show the status, so
* that there's something nice to see when people press Esc */
return plymouth_running();
}
void manager_status_printf(Manager *m, bool ephemeral, const char *status, const char *format, ...) {
va_list ap;
if (!manager_get_show_status(m))
return;
/* XXX We should totally drop the check for ephemeral here
* and thus effectively make 'Type=idle' pointless. */
if (ephemeral && m->n_on_console > 0)
return;
if (!manager_is_booting_or_shutting_down(m))
return;
va_start(ap, format);
status_vprintf(status, true, ephemeral, format, ap);
va_end(ap);
}
int manager_get_unit_by_path(Manager *m, const char *path, const char *suffix, Unit **_found) {
_cleanup_free_ char *p = NULL;
Unit *found;
assert(m);
assert(path);
assert(suffix);
assert(_found);
p = unit_name_from_path(path, suffix);
if (!p)
return -ENOMEM;
found = manager_get_unit(m, p);
if (!found) {
*_found = NULL;
return 0;
}
*_found = found;
return 1;
}
Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path) {
char p[strlen(path)+1];
assert(m);
assert(path);
strcpy(p, path);
path_kill_slashes(p);
return hashmap_get(m->units_requiring_mounts_for, streq(p, "/") ? "" : p);
}