manager.c revision 8a3a1704c7738a49385e1e1a2a5041f50e79f57e
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/***
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering This file is part of systemd.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Copyright 2010 Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering systemd is free software; you can redistribute it and/or modify it
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering under the terms of the GNU Lesser General Public License as published by
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering (at your option) any later version.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering systemd is distributed in the hope that it will be useful, but
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Lesser General Public License for more details.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering You should have received a copy of the GNU Lesser General Public License
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering***/
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering#include <assert.h>
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering#include <errno.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <string.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <sys/epoll.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <signal.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <sys/signalfd.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <sys/wait.h>
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering#include <unistd.h>
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering#include <sys/poll.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <sys/reboot.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <sys/ioctl.h>
6482f6269c87d2249e52e889a63adbdd50f2d691Ronny Chevalier#include <linux/kd.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <termios.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <fcntl.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <sys/types.h>
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#include <sys/stat.h>
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack#include <dirent.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <sys/timerfd.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#ifdef HAVE_AUDIT
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#include <libaudit.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#endif
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "systemd/sd-daemon.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "systemd/sd-id128.h"
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#include "systemd/sd-messages.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "manager.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "transaction.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "hashmap.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "macro.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "strv.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "log.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "util.h"
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering#include "mkdir.h"
4f10118016f9b2fd7e1d26c9ef7d91eb33fba694Lennart Poettering#include "ratelimit.h"
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#include "cgroup.h"
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#include "mount-setup.h"
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#include "unit-name.h"
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#include "dbus-unit.h"
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#include "dbus-job.h"
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#include "missing.h"
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#include "path-lookup.h"
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#include "special.h"
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#include "bus-errors.h"
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#include "exit-status.h"
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#include "virt.h"
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#include "watchdog.h"
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#include "cgroup-util.h"
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#include "path-util.h"
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#include "audit-fd.h"
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering/* As soon as 16 units are in our GC queue, make sure to run a gc sweep */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#define GC_QUEUE_ENTRIES_MAX 16
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering/* As soon as 5s passed since a unit was added to our GC queue, make sure to run a gc sweep */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#define GC_QUEUE_USEC_MAX (10*USEC_PER_SEC)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering/* Where clients shall send notification messages to */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#define NOTIFY_SOCKET "@/org/freedesktop/systemd1/notify"
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic int manager_setup_notify(Manager *m) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering union {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering struct sockaddr sa;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering struct sockaddr_un un;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering } sa;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering struct epoll_event ev;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering int one = 1;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(m);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->notify_watch.type = WATCH_NOTIFY;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->notify_watch.fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (m->notify_watch.fd < 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_error("Failed to allocate notification socket: %m");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -errno;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering zero(sa);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sa.sa.sa_family = AF_UNIX;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (getpid() != 1 || detect_container(NULL) > 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering snprintf(sa.un.sun_path, sizeof(sa.un.sun_path), NOTIFY_SOCKET "/%llu", random_ull());
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering else
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering strncpy(sa.un.sun_path, NOTIFY_SOCKET, sizeof(sa.un.sun_path));
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sa.un.sun_path[0] = 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (bind(m->notify_watch.fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_error("bind() failed: %m");
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return -errno;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (setsockopt(m->notify_watch.fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_error("SO_PASSCRED failed: %m");
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return -errno;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering zero(ev);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering ev.events = EPOLLIN;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering ev.data.ptr = &m->notify_watch;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->notify_watch.fd, &ev) < 0) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_error("Failed to add timer change fd to epoll: %m");
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return -errno;
7dfbe2e3fc0215b49d8202a32beb6b1aae08c4e4Tom Gundersen }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sa.un.sun_path[0] = '@';
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering m->notify_socket = strdup(sa.un.sun_path);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (!m->notify_socket)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return log_oom();
7dfbe2e3fc0215b49d8202a32beb6b1aae08c4e4Tom Gundersen
7dfbe2e3fc0215b49d8202a32beb6b1aae08c4e4Tom Gundersen log_debug("Using notification socket %s", m->notify_socket);
7dfbe2e3fc0215b49d8202a32beb6b1aae08c4e4Tom Gundersen
7dfbe2e3fc0215b49d8202a32beb6b1aae08c4e4Tom Gundersen return 0;
7dfbe2e3fc0215b49d8202a32beb6b1aae08c4e4Tom Gundersen}
7dfbe2e3fc0215b49d8202a32beb6b1aae08c4e4Tom Gundersen
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic int manager_setup_time_change(Manager *m) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering struct epoll_event ev;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering struct itimerspec its;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(m);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(m->time_change_watch.type == WATCH_INVALID);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Uses TFD_TIMER_CANCEL_ON_SET to get notifications whenever
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * CLOCK_REALTIME makes a jump relative to CLOCK_MONOTONIC */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->time_change_watch.type = WATCH_TIME_CHANGE;
b2c23da8cea1987a1a329f5a964d3299b7ca7890Lennart Poettering m->time_change_watch.fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (m->time_change_watch.fd < 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_error("Failed to create timerfd: %m");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -errno;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering zero(its);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* We only care for the cancellation event, hence we set the
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * timeout to the latest possible value. */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_cc(sizeof(time_t) == sizeof(long));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering its.it_value.tv_sec = LONG_MAX;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (timerfd_settime(m->time_change_watch.fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_debug("Failed to set up TFD_TIMER_CANCEL_ON_SET, ignoring: %m");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering close_nointr_nofail(m->time_change_watch.fd);
7410616cd9dbbec97cf98d75324da5cda2b2f7a2Lennart Poettering watch_init(&m->time_change_watch);
7410616cd9dbbec97cf98d75324da5cda2b2f7a2Lennart Poettering return 0;
7410616cd9dbbec97cf98d75324da5cda2b2f7a2Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering zero(ev);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering ev.events = EPOLLIN;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering ev.data.ptr = &m->time_change_watch;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->time_change_watch.fd, &ev) < 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_error("Failed to add timer change fd to epoll: %m");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -errno;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack }
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack log_debug("Set up TFD_TIMER_CANCEL_ON_SET timerfd.");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack return 0;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack}
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mackstatic int enable_special_signals(Manager *m) {
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack int fd;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack assert(m);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Enable that we get SIGINT on control-alt-del. In containers
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * this will fail with EPERM (older) or EINVAL (newer), so
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * ignore that. */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (reboot(RB_DISABLE_CAD) < 0 && errno != EPERM && errno != EINVAL)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_warning("Failed to enable ctrl-alt-del handling: %m");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (fd < 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Support systems without virtual console */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (fd != -ENOENT)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_warning("Failed to open /dev/tty0: %m");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering } else {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Enable that we get SIGWINCH on kbrequest */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (ioctl(fd, KDSIGACCEPT, SIGWINCH) < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_warning("Failed to enable kbrequest handling: %s", strerror(errno));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering close_nointr_nofail(fd);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poetteringstatic int manager_setup_signals(Manager *m) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering sigset_t mask;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering struct epoll_event ev;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering struct sigaction sa;
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(m);
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* We are not interested in SIGSTOP and friends. */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering zero(sa);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering sa.sa_handler = SIG_DFL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering sa.sa_flags = SA_NOCLDSTOP|SA_RESTART;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_se(sigemptyset(&mask) == 0);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering sigset_add_many(&mask,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGCHLD, /* Child died */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGTERM, /* Reexecute daemon */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGHUP, /* Reload configuration */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGUSR1, /* systemd/upstart: reconnect to D-Bus */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGUSR2, /* systemd: dump status */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGINT, /* Kernel sends us this on control-alt-del */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGWINCH, /* Kernel sends us this on kbrequest (alt-arrowup) */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGPWR, /* Some kernel drivers and upsd send us this on power failure */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGRTMIN+0, /* systemd: start default.target */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGRTMIN+1, /* systemd: isolate rescue.target */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGRTMIN+2, /* systemd: isolate emergency.target */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGRTMIN+3, /* systemd: start halt.target */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGRTMIN+4, /* systemd: start poweroff.target */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGRTMIN+5, /* systemd: start reboot.target */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGRTMIN+6, /* systemd: start kexec.target */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGRTMIN+13, /* systemd: Immediate halt */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGRTMIN+14, /* systemd: Immediate poweroff */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGRTMIN+15, /* systemd: Immediate reboot */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGRTMIN+16, /* systemd: Immediate kexec */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGRTMIN+20, /* systemd: enable status messages */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGRTMIN+21, /* systemd: disable status messages */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGRTMIN+22, /* systemd: set log level to LOG_DEBUG */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGRTMIN+23, /* systemd: set log level to LOG_INFO */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGRTMIN+24, /* systemd: Immediate exit (--user only) */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGRTMIN+26, /* systemd: set log target to journal-or-kmsg */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGRTMIN+27, /* systemd: set log target to console */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SIGRTMIN+28, /* systemd: set log target to kmsg */
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering SIGRTMIN+29, /* systemd: set log target to syslog-or-kmsg */
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack -1);
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->signal_watch.type = WATCH_SIGNAL;
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering m->signal_watch.fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack if (m->signal_watch.fd < 0)
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering return -errno;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering zero(ev);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering ev.events = EPOLLIN;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering ev.data.ptr = &m->signal_watch;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->signal_watch.fd, &ev) < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -errno;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (m->running_as == SYSTEMD_SYSTEM)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return enable_special_signals(m);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void manager_strip_environment(Manager *m) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(m);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering /* Remove variables from the inherited set that are part of
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * the container interface:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * http://www.freedesktop.org/wiki/Software/systemd/ContainerInterface */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering strv_remove_prefix(m->environment, "container=");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering strv_remove_prefix(m->environment, "container_");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Remove variables from the inherited set that are part of
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * the initrd interface:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * http://www.freedesktop.org/wiki/Software/systemd/InitrdInterface */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering strv_remove_prefix(m->environment, "RD_");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringint manager_new(SystemdRunningAs running_as, Manager **_m) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Manager *m;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering int r = -ENOMEM;
cfa9677bd164574600d29a9bf99f9d1f28a7a170Mantas MikulÄ—nas
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(_m);
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering assert(running_as >= 0);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(running_as < _SYSTEMD_RUNNING_AS_MAX);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m = new0(Manager, 1);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!m)
cfa9677bd164574600d29a9bf99f9d1f28a7a170Mantas MikulÄ—nas return -ENOMEM;
cfa9677bd164574600d29a9bf99f9d1f28a7a170Mantas MikulÄ—nas
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering dual_timestamp_get(&m->userspace_timestamp);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->running_as = running_as;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->name_data_slot = m->conn_data_slot = m->subscribed_data_slot = -1;
8f077bf94e129fa1b6f0159e3140c4326f1066cfZbigniew Jędrzejewski-Szmek m->exit_code = _MANAGER_EXIT_CODE_INVALID;
8f077bf94e129fa1b6f0159e3140c4326f1066cfZbigniew Jędrzejewski-Szmek m->pin_cgroupfs_fd = -1;
8f077bf94e129fa1b6f0159e3140c4326f1066cfZbigniew Jędrzejewski-Szmek m->idle_pipe[0] = m->idle_pipe[1] = -1;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering watch_init(&m->signal_watch);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering watch_init(&m->mount_watch);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering watch_init(&m->swap_watch);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering watch_init(&m->udev_watch);
b2c23da8cea1987a1a329f5a964d3299b7ca7890Lennart Poettering watch_init(&m->time_change_watch);
8f077bf94e129fa1b6f0159e3140c4326f1066cfZbigniew Jędrzejewski-Szmek
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt m->epoll_fd = m->dev_autofs_fd = -1;
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->environment = strv_copy(environ);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!m->environment)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering goto fail;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering manager_strip_environment(m);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (running_as == SYSTEMD_SYSTEM) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->default_controllers = strv_new("cpu", NULL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!m->default_controllers)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering goto fail;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (!(m->units = hashmap_new(string_hash_func, string_compare_func)))
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering goto fail;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!(m->jobs = hashmap_new(trivial_hash_func, trivial_compare_func)))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering goto fail;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (!(m->watch_pids = hashmap_new(trivial_hash_func, trivial_compare_func)))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering goto fail;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!(m->cgroup_bondings = hashmap_new(string_hash_func, string_compare_func)))
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering goto fail;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!(m->watch_bus = hashmap_new(string_hash_func, string_compare_func)))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering goto fail;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
be847e82cf95bf8eb589778df2aa2b3d1d7ae99eLennart Poettering m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (m->epoll_fd < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering goto fail;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = manager_setup_signals(m);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering goto fail;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = manager_setup_cgroup(m);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering goto fail;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = manager_setup_notify(m);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering goto fail;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = manager_setup_time_change(m);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering goto fail;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* Try to connect to the busses, if possible. */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = bus_init(m, running_as != SYSTEMD_SYSTEM);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering goto fail;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->taint_usr = dir_is_empty("/usr") > 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *_m = m;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringfail:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering manager_free(m);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic unsigned manager_dispatch_cleanup_queue(Manager *m) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Unit *u;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unsigned n = 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(m);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering while ((u = m->cleanup_queue)) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(u->in_cleanup_queue);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering unit_free(u);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering n++;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return n;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringenum {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering GC_OFFSET_IN_PATH, /* This one is on the path we were traveling */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering GC_OFFSET_UNSURE, /* No clue */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering GC_OFFSET_GOOD, /* We still need this unit */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering GC_OFFSET_BAD, /* We don't need this unit anymore */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering _GC_OFFSET_MAX
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering};
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic void unit_gc_sweep(Unit *u, unsigned gc_marker) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering Iterator i;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering Unit *other;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering bool is_bad;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(u);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (u->gc_marker == gc_marker + GC_OFFSET_GOOD ||
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering u->gc_marker == gc_marker + GC_OFFSET_BAD ||
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering u->gc_marker == gc_marker + GC_OFFSET_IN_PATH)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (u->in_cleanup_queue)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering goto bad;
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (unit_check_gc(u))
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering goto good;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering u->gc_marker = gc_marker + GC_OFFSET_IN_PATH;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering is_bad = true;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering SET_FOREACH(other, u->dependencies[UNIT_REFERENCED_BY], i) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering unit_gc_sweep(other, gc_marker);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (other->gc_marker == gc_marker + GC_OFFSET_GOOD)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering goto good;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (other->gc_marker != gc_marker + GC_OFFSET_BAD)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering is_bad = false;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (is_bad)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering goto bad;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* We were unable to find anything out about this entry, so
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * let's investigate it later */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering u->gc_marker = gc_marker + GC_OFFSET_UNSURE;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unit_add_to_gc_queue(u);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringbad:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* We definitely know that this one is not useful anymore, so
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * let's mark it for deletion */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering u->gc_marker = gc_marker + GC_OFFSET_BAD;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unit_add_to_cleanup_queue(u);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringgood:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering u->gc_marker = gc_marker + GC_OFFSET_GOOD;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic unsigned manager_dispatch_gc_queue(Manager *m) {
db2cb23b5b179707000d28a11efb3d888d06ee80Umut Tezduyar Lindskog Unit *u;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering unsigned n = 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering unsigned gc_marker;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(m);
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if ((m->n_in_gc_queue < GC_QUEUE_ENTRIES_MAX) &&
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering (m->gc_queue_timestamp <= 0 ||
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering (m->gc_queue_timestamp + GC_QUEUE_USEC_MAX) > now(CLOCK_MONOTONIC)))
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_debug("Running GC...");
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering m->gc_marker += _GC_OFFSET_MAX;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (m->gc_marker + _GC_OFFSET_MAX <= _GC_OFFSET_MAX)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering m->gc_marker = 1;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering gc_marker = m->gc_marker;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering while ((u = m->gc_queue)) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(u->in_gc_queue);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering unit_gc_sweep(u, gc_marker);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering LIST_REMOVE(Unit, gc_queue, m->gc_queue, u);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering u->in_gc_queue = false;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering n++;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (u->gc_marker == gc_marker + GC_OFFSET_BAD ||
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering u->gc_marker == gc_marker + GC_OFFSET_UNSURE) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_debug("Collecting %s", u->id);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering u->gc_marker = gc_marker + GC_OFFSET_BAD;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack unit_add_to_cleanup_queue(u);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack }
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack }
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack m->n_in_gc_queue = 0;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack m->gc_queue_timestamp = 0;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack return n;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack}
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void manager_clear_jobs_and_units(Manager *m) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Unit *u;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(m);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering while ((u = hashmap_first(m->units)))
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering unit_free(u);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering manager_dispatch_cleanup_queue(m);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(!m->load_queue);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(!m->run_queue);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(!m->dbus_unit_queue);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(!m->dbus_job_queue);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(!m->cleanup_queue);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(!m->gc_queue);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
8d0e0ddda6501479eb69164687c83c1a7667b33aJan Engelhardt assert(hashmap_isempty(m->jobs));
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(hashmap_isempty(m->units));
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringvoid manager_free(Manager *m) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering UnitType c;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering int i;
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(m);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering manager_clear_jobs_and_units(m);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering for (c = 0; c < _UNIT_TYPE_MAX; c++)
8d0e0ddda6501479eb69164687c83c1a7667b33aJan Engelhardt if (unit_vtable[c]->shutdown)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering unit_vtable[c]->shutdown(m);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* If we reexecute ourselves, we keep the root cgroup
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * around */
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering manager_shutdown_cgroup(m, m->exit_code != MANAGER_REEXECUTE);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering manager_undo_generators(m);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering bus_done(m);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering hashmap_free(m->units);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering hashmap_free(m->jobs);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering hashmap_free(m->watch_pids);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering hashmap_free(m->watch_bus);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (m->epoll_fd >= 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering close_nointr_nofail(m->epoll_fd);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (m->signal_watch.fd >= 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering close_nointr_nofail(m->signal_watch.fd);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (m->notify_watch.fd >= 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering close_nointr_nofail(m->notify_watch.fd);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (m->time_change_watch.fd >= 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering close_nointr_nofail(m->time_change_watch.fd);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering free(m->notify_socket);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack lookup_paths_free(&m->lookup_paths);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack strv_free(m->environment);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
05a08cb60f02970e8476306074c70ee4e6a57fb3Thomas Hindoe Paaboel Andersen strv_free(m->default_controllers);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering hashmap_free(m->cgroup_bondings);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering set_free_free(m->unit_path_cache);
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering close_pipe(m->idle_pipe);
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering
ff975efb2e88dcd5221a2f0d76c4c87e85b821a8Lennart Poettering free(m->switch_root);
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering free(m->switch_root_init);
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering for (i = 0; i < RLIMIT_NLIMITS; i++)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering free(m->rlimit[i]);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering free(m);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint manager_enumerate(Manager *m) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering int r = 0, q;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering UnitType c;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(m);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Let's ask every type to load all units from disk/kernel
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * that it might know */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering for (c = 0; c < _UNIT_TYPE_MAX; c++)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (unit_vtable[c]->enumerate)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if ((q = unit_vtable[c]->enumerate(m)) < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = q;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering manager_dispatch_load_queue(m);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint manager_coldplug(Manager *m) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering int r = 0, q;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Iterator i;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Unit *u;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering char *k;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(m);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* Then, let's set up their initial state. */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering HASHMAP_FOREACH_KEY(u, k, m->units, i) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* ignore aliases */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (u->id != k)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering continue;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if ((q = unit_coldplug(u)) < 0)
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack r = q;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poetteringstatic void manager_build_unit_path_cache(Manager *m) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering char **i;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering DIR *d = NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering int r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(m);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering set_free_free(m->unit_path_cache);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!(m->unit_path_cache = set_new(string_hash_func, string_compare_func))) {
82a2b6bb5e4e5d294f09af778c48974a7857afb6Lennart Poettering log_error("Failed to allocate unit path cache.");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* This simply builds a list of files we know exist, so that
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * we don't always have to go to disk */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering STRV_FOREACH(i, m->lookup_paths.unit_path) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering struct dirent *de;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (!(d = opendir(*i))) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_error("Failed to open directory: %m");
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering continue;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering while ((de = readdir(d))) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering char *p;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (ignore_file(de->d_name))
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering continue;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering p = strjoin(streq(*i, "/") ? "" : *i, "/", de->d_name, NULL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!p) {
82a2b6bb5e4e5d294f09af778c48974a7857afb6Lennart Poettering r = -ENOMEM;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering goto fail;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if ((r = set_put(m->unit_path_cache, p)) < 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering free(p);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering goto fail;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering closedir(d);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering d = NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringfail:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_error("Failed to build unit path cache: %s", strerror(-r));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering set_free_free(m->unit_path_cache);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->unit_path_cache = NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (d)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering closedir(d);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering int r, q;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(m);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering manager_run_generators(m);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = lookup_paths_init(
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering &m->lookup_paths, m->running_as, true,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->generator_unit_path,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->generator_unit_path_early,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->generator_unit_path_late);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering manager_build_unit_path_cache(m);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* If we will deserialize make sure that during enumeration
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * this is already known, so we increase the counter here
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * already */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (serialization)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->n_reloading ++;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* First, enumerate what we can from all config files */
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering r = manager_enumerate(m);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Second, deserialize if there is something to deserialize */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (serialization) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering q = manager_deserialize(m, serialization, fds);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (q < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = q;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* Third, fire things up! */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering q = manager_coldplug(m);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (q < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = q;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (serialization) {
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering assert(m->n_reloading > 0);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->n_reloading --;
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool override, DBusError *e, Job **_ret) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering int r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Transaction *tr;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(m);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(type < _JOB_TYPE_MAX);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(unit);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(mode < _JOB_MODE_MAX);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (mode == JOB_ISOLATE && type != JOB_START) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering dbus_set_error(e, BUS_ERROR_INVALID_JOB_MODE, "Isolate is only valid for start.");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -EINVAL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (mode == JOB_ISOLATE && !unit->allow_isolate) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering dbus_set_error(e, BUS_ERROR_NO_ISOLATION, "Operation refused, unit may not be isolated.");
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering return -EPERM;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering }
94e15fdc4d9d96fa6607bfb4eaaea164a3aec417David Herrmann
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering log_debug("Trying to enqueue job %s/%s/%s", unit->id, job_type_to_string(type), job_mode_to_string(mode));
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
e24e415e5f3af2fe86d2be9a1f1a2e8d5f8c96bfDaniel Mack job_type_collapse(&type, unit);
e24e415e5f3af2fe86d2be9a1f1a2e8d5f8c96bfDaniel Mack
e24e415e5f3af2fe86d2be9a1f1a2e8d5f8c96bfDaniel Mack tr = transaction_new();
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering if (!tr)
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering return -ENOMEM;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering r = transaction_add_job_and_dependencies(tr, type, unit, NULL, true, override, false,
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering mode == JOB_IGNORE_DEPENDENCIES || mode == JOB_IGNORE_REQUIREMENTS,
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering mode == JOB_IGNORE_DEPENDENCIES, e);
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering if (r < 0)
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering goto tr_abort;
dcc2fc01fa850e9ee36c549dc2691e7e5c71bebfLennart Poettering
dcc2fc01fa850e9ee36c549dc2691e7e5c71bebfLennart Poettering if (mode == JOB_ISOLATE) {
dcc2fc01fa850e9ee36c549dc2691e7e5c71bebfLennart Poettering r = transaction_add_isolate_jobs(tr, m);
dcc2fc01fa850e9ee36c549dc2691e7e5c71bebfLennart Poettering if (r < 0)
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering goto tr_abort;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering }
dcc2fc01fa850e9ee36c549dc2691e7e5c71bebfLennart Poettering
dcc2fc01fa850e9ee36c549dc2691e7e5c71bebfLennart Poettering r = transaction_activate(tr, m, mode, e);
dcc2fc01fa850e9ee36c549dc2691e7e5c71bebfLennart Poettering if (r < 0)
dcc2fc01fa850e9ee36c549dc2691e7e5c71bebfLennart Poettering goto tr_abort;
dcc2fc01fa850e9ee36c549dc2691e7e5c71bebfLennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering log_debug("Enqueued job %s/%s as %u", unit->id, job_type_to_string(type), (unsigned) tr->anchor_job->id);
94e15fdc4d9d96fa6607bfb4eaaea164a3aec417David Herrmann
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering if (_ret)
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering *_ret = tr->anchor_job;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering transaction_free(tr);
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering return 0;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poetteringtr_abort:
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering transaction_abort(tr);
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering transaction_free(tr);
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering return r;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering}
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poetteringint manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, bool override, DBusError *e, Job **_ret) {
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering Unit *unit;
a9c8343e83ec09f80a76930573b2592f97ae4283Daniel Mack int r;
a9c8343e83ec09f80a76930573b2592f97ae4283Daniel Mack
a9c8343e83ec09f80a76930573b2592f97ae4283Daniel Mack assert(m);
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering assert(type < _JOB_TYPE_MAX);
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering assert(name);
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering assert(mode < _JOB_MODE_MAX);
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering r = manager_load_unit(m, name, NULL, NULL, &unit);
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering if (r < 0)
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering return r;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering return manager_add_job(m, type, unit, mode, override, e, _ret);
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering}
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart PoetteringJob *manager_get_job(Manager *m, uint32_t id) {
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering assert(m);
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering return hashmap_get(m->jobs, UINT32_TO_PTR(id));
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering}
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart PoetteringUnit *manager_get_unit(Manager *m, const char *name) {
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering assert(m);
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering assert(name);
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering return hashmap_get(m->units, name);
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering}
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poetteringunsigned manager_dispatch_load_queue(Manager *m) {
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering Unit *u;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering unsigned n = 0;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering assert(m);
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
a9c8343e83ec09f80a76930573b2592f97ae4283Daniel Mack /* Make sure we are not run recursively */
dcc2fc01fa850e9ee36c549dc2691e7e5c71bebfLennart Poettering if (m->dispatching_load_queue)
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering return 0;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering m->dispatching_load_queue = true;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering /* Dispatches the load queue. Takes a unit from the queue and
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * tries to load its data until the queue is empty */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering while ((u = m->load_queue)) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(u->in_load_queue);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unit_load(u);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering n++;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering m->dispatching_load_queue = false;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return n;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint manager_load_unit_prepare(Manager *m, const char *name, const char *path, DBusError *e, Unit **_ret) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Unit *ret;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering UnitType t;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering int r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(m);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(name || path);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* This will prepare the unit for loading, but not actually
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * load anything from disk. */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (path && !is_path(path)) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering dbus_set_error(e, BUS_ERROR_INVALID_PATH, "Path %s is not absolute.", path);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return -EINVAL;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (!name)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering name = path_get_file_name(path);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering t = unit_name_to_type(name);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (t == _UNIT_TYPE_INVALID || !unit_name_is_valid(name, false)) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering dbus_set_error(e, BUS_ERROR_INVALID_NAME, "Unit name %s is not valid.", name);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return -EINVAL;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering ret = manager_get_unit(m, name);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (ret) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering *_ret = ret;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return 1;
deffddf1df29a5ed047feff3a0f2b765006fb71bLukas Nykryn }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering ret = unit_new(m, unit_vtable[t]->object_size);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (!ret)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return -ENOMEM;
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering if (path) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering ret->fragment_path = strdup(path);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (!ret->fragment_path) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering unit_free(ret);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return -ENOMEM;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if ((r = unit_add_name(ret, name)) < 0) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering unit_free(ret);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering unit_add_to_load_queue(ret);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering unit_add_to_dbus_queue(ret);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering unit_add_to_gc_queue(ret);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (_ret)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering *_ret = ret;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringint manager_load_unit(Manager *m, const char *name, const char *path, DBusError *e, Unit **_ret) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering int r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(m);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* This will load the service information files, but not actually
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * start any services or anything. */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = manager_load_unit_prepare(m, name, path, e, _ret);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r != 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering manager_dispatch_load_queue(m);
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (_ret)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering *_ret = unit_follow_merge(*_ret);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return 0;
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringvoid manager_dump_jobs(Manager *s, FILE *f, const char *prefix) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering Iterator i;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering Job *j;
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(s);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(f);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering HASHMAP_FOREACH(j, s->jobs, i)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering job_dump(j, f, prefix);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringvoid manager_dump_units(Manager *s, FILE *f, const char *prefix) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering Iterator i;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering Unit *u;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering const char *t;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(f);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering HASHMAP_FOREACH_KEY(u, t, s->units, i)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (u->id == t)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unit_dump(u, f, prefix);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringvoid manager_clear_jobs(Manager *m) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Job *j;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(m);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering while ((j = hashmap_first(m->jobs)))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* No need to recurse. We're cancelling all jobs. */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering job_finish_and_invalidate(j, JOB_CANCELED, false);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringunsigned manager_dispatch_run_queue(Manager *m) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Job *j;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unsigned n = 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (m->dispatching_run_queue)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering m->dispatching_run_queue = true;
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering while ((j = m->run_queue)) {
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering assert(j->installed);
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering assert(j->in_run_queue);
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering job_run_and_invalidate(j);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering n++;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering m->dispatching_run_queue = false;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return n;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringunsigned manager_dispatch_dbus_queue(Manager *m) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering Job *j;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering Unit *u;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering unsigned n = 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(m);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (m->dispatching_dbus_queue)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering m->dispatching_dbus_queue = true;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering while ((u = m->dbus_unit_queue)) {
1c2e9646e4a1720fc8ad35c705c195ae1a2c5ce0Lennart Poettering assert(u->in_dbus_queue);
d69a7ceaed77992105342a056fe68769c2e6d3bdJohannes Hölzl
0faacd470dfbd24f4c6504da6f04213aa05f9d19Lennart Poettering bus_unit_send_change_signal(u);
0faacd470dfbd24f4c6504da6f04213aa05f9d19Lennart Poettering n++;
d79acc309327f8c0863bd3da8b93d926a1c93ba1David Herrmann }
0faacd470dfbd24f4c6504da6f04213aa05f9d19Lennart Poettering
0faacd470dfbd24f4c6504da6f04213aa05f9d19Lennart Poettering while ((j = m->dbus_job_queue)) {
0faacd470dfbd24f4c6504da6f04213aa05f9d19Lennart Poettering assert(j->in_dbus_queue);
0faacd470dfbd24f4c6504da6f04213aa05f9d19Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering bus_job_send_change_signal(j);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering n++;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering m->dispatching_dbus_queue = false;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return n;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic int manager_process_notify_fd(Manager *m) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering ssize_t n;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(m);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering for (;;) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering char buf[4096];
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering struct msghdr msghdr;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering struct iovec iovec;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering struct ucred *ucred;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering union {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering struct cmsghdr cmsghdr;
700ff4d97311902a440109a2c081731ab6ae8a20Lennart Poettering uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering } control;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Unit *u;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering char **tags;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering zero(iovec);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering iovec.iov_base = buf;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering iovec.iov_len = sizeof(buf)-1;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering zero(control);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering zero(msghdr);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering msghdr.msg_iov = &iovec;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering msghdr.msg_iovlen = 1;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering msghdr.msg_control = &control;
e05ad7bcc87f652cea321224f8eeb32e21d18e0cLennart Poettering msghdr.msg_controllen = sizeof(control);
e05ad7bcc87f652cea321224f8eeb32e21d18e0cLennart Poettering
e05ad7bcc87f652cea321224f8eeb32e21d18e0cLennart Poettering if ((n = recvmsg(m->notify_watch.fd, &msghdr, MSG_DONTWAIT)) <= 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (n >= 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -EIO;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (errno == EAGAIN || errno == EINTR)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering break;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -errno;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (msghdr.msg_controllen < CMSG_LEN(sizeof(struct ucred)) ||
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering control.cmsghdr.cmsg_level != SOL_SOCKET ||
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering control.cmsghdr.cmsg_type != SCM_CREDENTIALS ||
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering control.cmsghdr.cmsg_len != CMSG_LEN(sizeof(struct ucred))) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_warning("Received notify message without credentials. Ignoring.");
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering continue;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!(u = hashmap_get(m->watch_pids, LONG_TO_PTR(ucred->pid))))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!(u = cgroup_unit_by_pid(m, ucred->pid))) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_warning("Cannot find unit for notify message of PID %lu.", (unsigned long) ucred->pid);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering continue;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert((size_t) n < sizeof(buf));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering buf[n] = 0;
0faacd470dfbd24f4c6504da6f04213aa05f9d19Lennart Poettering if (!(tags = strv_split(buf, "\n\r")))
0faacd470dfbd24f4c6504da6f04213aa05f9d19Lennart Poettering return -ENOMEM;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_debug("Got notification message for unit %s", u->id);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (UNIT_VTABLE(u)->notify_message)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering UNIT_VTABLE(u)->notify_message(u, ucred->pid, tags);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering strv_free(tags);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic int manager_dispatch_sigchld(Manager *m) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(m);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering for (;;) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering siginfo_t si;
Unit *u;
int r;
zero(si);
/* 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) {
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));
free(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. */
if ((r = manager_process_notify_fd(m)) < 0)
return r;
/* And now figure out the unit this belongs to */
if (!(u = hashmap_get(m->watch_pids, LONG_TO_PTR(si.si_pid))))
u = cgroup_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("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) {
int r;
DBusError error;
dbus_error_init(&error);
log_debug("Activating special unit %s", name);
if ((r = manager_add_job_by_name(m, JOB_START, name, mode, true, &error, NULL)) < 0)
log_error("Failed to enqueue %s job: %s", name, bus_error(&error, r));
dbus_error_free(&error);
return r;
}
static int manager_process_signal_fd(Manager *m) {
ssize_t n;
struct signalfd_siginfo sfsi;
bool sigchld = false;
assert(m);
for (;;) {
if ((n = read(m->signal_watch.fd, &sfsi, sizeof(sfsi))) != 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);
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: {
FILE *f;
char *dump = NULL;
size_t size;
if (!(f = open_memstream(&dump, &size))) {
log_warning("Failed to allocate memory stream.");
break;
}
manager_dump_units(m, f, "\t");
manager_dump_jobs(m, f, "\t");
if (ferror(f)) {
fclose(f);
free(dump);
log_warning("Failed to write status stream");
break;
}
fclose(f);
log_dump(LOG_INFO, dump);
free(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 process_event(Manager *m, struct epoll_event *ev) {
int r;
Watch *w;
assert(m);
assert(ev);
assert_se(w = ev->data.ptr);
if (w->type == WATCH_INVALID)
return 0;
switch (w->type) {
case WATCH_SIGNAL:
/* An incoming signal? */
if (ev->events != EPOLLIN)
return -EINVAL;
if ((r = manager_process_signal_fd(m)) < 0)
return r;
break;
case WATCH_NOTIFY:
/* An incoming daemon notification event? */
if (ev->events != EPOLLIN)
return -EINVAL;
if ((r = manager_process_notify_fd(m)) < 0)
return r;
break;
case WATCH_FD:
/* Some fd event, to be dispatched to the units */
UNIT_VTABLE(w->data.unit)->fd_event(w->data.unit, w->fd, ev->events, w);
break;
case WATCH_UNIT_TIMER:
case WATCH_JOB_TIMER: {
uint64_t v;
ssize_t k;
/* Some timer event, to be dispatched to the units */
k = read(w->fd, &v, sizeof(v));
if (k != sizeof(v)) {
if (k < 0 && (errno == EINTR || errno == EAGAIN))
break;
log_error("Failed to read timer event counter: %s", k < 0 ? strerror(-k) : "Short read");
return k < 0 ? -errno : -EIO;
}
if (w->type == WATCH_UNIT_TIMER)
UNIT_VTABLE(w->data.unit)->timer_event(w->data.unit, v, w);
else
job_timer_event(w->data.job, v, w);
break;
}
case WATCH_MOUNT:
/* Some mount table change, intended for the mount subsystem */
mount_fd_event(m, ev->events);
break;
case WATCH_SWAP:
/* Some swap table change, intended for the swap subsystem */
swap_fd_event(m, ev->events);
break;
case WATCH_UDEV:
/* Some notification from udev, intended for the device subsystem */
device_fd_event(m, ev->events);
break;
case WATCH_DBUS_WATCH:
bus_watch_event(m, w, ev->events);
break;
case WATCH_DBUS_TIMEOUT:
bus_timeout_event(m, w, ev->events);
break;
case WATCH_TIME_CHANGE: {
Unit *u;
Iterator i;
log_struct(LOG_INFO,
MESSAGE_ID(SD_MESSAGE_TIME_CHANGE),
"MESSAGE=Time has been changed",
NULL);
/* Restart the watch */
close_nointr_nofail(m->time_change_watch.fd);
watch_init(&m->time_change_watch);
manager_setup_time_change(m);
HASHMAP_FOREACH(u, m->units, i) {
if (UNIT_VTABLE(u)->time_change)
UNIT_VTABLE(u)->time_change(u);
}
break;
}
default:
log_error("event type=%i", w->type);
assert_not_reached("Unknown epoll event type.");
}
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. Leat's reap them */
r = manager_dispatch_sigchld(m);
if (r < 0)
return r;
while (m->exit_code == MANAGER_RUNNING) {
struct epoll_event event;
int n;
int wait_msec = -1;
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_run_queue(m) > 0)
continue;
if (bus_dispatch(m) > 0)
continue;
if (manager_dispatch_cleanup_queue(m) > 0)
continue;
if (manager_dispatch_gc_queue(m) > 0)
continue;
if (manager_dispatch_dbus_queue(m) > 0)
continue;
if (swap_dispatch_reload(m) > 0)
continue;
/* Sleep for half the watchdog time */
if (m->runtime_watchdog > 0 && m->running_as == SYSTEMD_SYSTEM) {
wait_msec = (int) (m->runtime_watchdog / 2 / USEC_PER_MSEC);
if (wait_msec <= 0)
wait_msec = 1;
} else
wait_msec = -1;
n = epoll_wait(m->epoll_fd, &event, 1, wait_msec);
if (n < 0) {
if (errno == EINTR)
continue;
return -errno;
} else if (n == 0)
continue;
assert(n == 1);
r = process_event(m, &event);
if (r < 0)
return r;
}
return m->exit_code;
}
int manager_load_unit_from_dbus_path(Manager *m, const char *s, DBusError *e, Unit **_u) {
char *n;
Unit *u;
int r;
assert(m);
assert(s);
assert(_u);
if (!startswith(s, "/org/freedesktop/systemd1/unit/"))
return -EINVAL;
n = bus_path_unescape(s+31);
if (!n)
return -ENOMEM;
r = manager_load_unit(m, n, NULL, e, &u);
free(n);
if (r < 0)
return r;
*_u = u;
return 0;
}
int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j) {
Job *j;
unsigned id;
int r;
assert(m);
assert(s);
assert(_j);
if (!startswith(s, "/org/freedesktop/systemd1/job/"))
return -EINVAL;
r = safe_atou(s + 30, &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;
if (!(p = unit_name_to_prefix_and_instance(u->id))) {
log_error("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 (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 */
if ((fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0)) < 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);
if (!(u = hashmap_get(m->watch_bus, name)))
return;
UNIT_VTABLE(u)->bus_name_owner_change(u, name, old_owner, new_owner);
}
void manager_dispatch_bus_query_pid_done(
Manager *m,
const char *name,
pid_t pid) {
Unit *u;
assert(m);
assert(name);
assert(pid >= 1);
if (!(u = hashmap_get(m->watch_bus, name)))
return;
UNIT_VTABLE(u)->bus_query_pid_done(u, name, pid);
}
int manager_open_serialization(Manager *m, FILE **_f) {
char *path = NULL;
mode_t saved_umask;
int fd;
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;
saved_umask = umask(0077);
fd = mkostemp(path, O_RDWR|O_CLOEXEC);
umask(saved_umask);
if (fd < 0) {
free(path);
return -errno;
}
unlink(path);
log_debug("Serializing state to %s", path);
free(path);
if (!(f = fdopen(fd, "w+")))
return -errno;
*_f = f;
return 0;
}
int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool serialize_jobs) {
Iterator i;
Unit *u;
const char *t;
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, "kernel-timestamp", &m->kernel_timestamp);
dual_timestamp_serialize(f, "loader-timestamp", &m->loader_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);
}
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);
if ((r = unit_serialize(u, f, fds, serialize_jobs)) < 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;
if ((b = parse_boolean(l+10)) < 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
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);
if ((r = manager_load_unit(m, strstrip(name), NULL, NULL, &u)) < 0)
goto finish;
if ((r = unit_deserialize(u, f, fds)) < 0)
goto finish;
}
finish:
if (ferror(f)) {
r = -EIO;
goto finish;
}
assert(m->n_reloading > 0);
m->n_reloading --;
return r;
}
int manager_reload(Manager *m) {
int r, q;
FILE *f;
FDSet *fds;
assert(m);
r = manager_open_serialization(m, &f);
if (r < 0)
return r;
m->n_reloading ++;
fds = fdset_new();
if (!fds) {
m->n_reloading --;
r = -ENOMEM;
goto finish;
}
r = manager_serialize(m, f, fds, true);
if (r < 0) {
m->n_reloading --;
goto finish;
}
if (fseeko(f, 0, SEEK_SET) < 0) {
m->n_reloading --;
r = -errno;
goto finish;
}
/* 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--;
finish:
if (f)
fclose(f);
if (fds)
fdset_free(fds);
return r;
}
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;
}
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_pending_inactive(Manager *m, const char *name) {
Unit *u;
assert(m);
assert(name);
/* Returns true if the unit is inactive or going down */
if (!(u = manager_get_unit(m, name)))
return true;
return unit_pending_inactive(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 (hashmap_size(m->jobs) > 0)
return;
/* Notify Type=idle units that we are done now */
close_pipe(m->idle_pipe);
/* 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),
format_timespan(initrd, sizeof(initrd), initrd_usec),
format_timespan(userspace, sizeof(userspace), userspace_usec),
format_timespan(sum, sizeof(sum), total_usec),
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),
format_timespan(userspace, sizeof(userspace), userspace_usec),
format_timespan(sum, sizeof(sum), total_usec),
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),
NULL);
}
bus_broadcast_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));
}
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", strerror(-r));
free(p);
return r;
}
} else {
p = strjoin("/tmp/systemd-", name, ".XXXXXX", NULL);
if (!p)
return log_oom();
if (!mkdtemp(p)) {
free(p);
log_error("Failed to create generator directory: %m");
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) {
DIR *d = NULL;
const char *generator_path;
const char *argv[5];
mode_t u;
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: %m");
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;
u = umask(0022);
execute_directory(generator_path, d, (char**) argv);
umask(u);
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);
finish:
if (d)
closedir(d);
}
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_set_default_controllers(Manager *m, char **controllers) {
char **l;
assert(m);
l = strv_copy(controllers);
if (!l)
return -ENOMEM;
strv_free(m->default_controllers);
m->default_controllers = l;
cg_shorten_controllers(m->default_controllers);
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");
}
bool manager_get_show_status(Manager *m) {
assert(m);
if (m->running_as != SYSTEMD_SYSTEM)
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 watch_init(Watch *w) {
assert(w);
w->type = WATCH_INVALID;
w->fd = -1;
}