manager.c revision a0b6422689e37ffee37742d027f91af8bacfa78d
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering This file is part of systemd.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Copyright 2010 Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is free software; you can redistribute it and/or modify it
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering under the terms of the GNU Lesser General Public License as published by
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (at your option) any later version.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is distributed in the hope that it will be useful, but
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Lesser General Public License for more details.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering You should have received a copy of the GNU Lesser General Public License
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering/* As soon as 16 units are in our GC queue, make sure to run a gc sweep */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/* As soon as 5s passed since a unit was added to our GC queue, make sure to run a gc sweep */
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering#define GC_QUEUE_USEC_MAX (10*USEC_PER_SEC)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/* Initial delay and the interval for printing status messages about running jobs */
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering/* Where clients shall send notification messages to */
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering#define NOTIFY_SOCKET "@/org/freedesktop/systemd1/notify"
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering#define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poetteringstatic int manager_setup_notify(Manager *m) {
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering m->notify_watch.fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering log_error("Failed to allocate notification socket: %m");
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (getpid() != 1 || detect_container(NULL) > 0)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering snprintf(sa.un.sun_path, sizeof(sa.un.sun_path), NOTIFY_SOCKET "/%llu", random_ull());
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering strncpy(sa.un.sun_path, NOTIFY_SOCKET, sizeof(sa.un.sun_path));
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (bind(m->notify_watch.fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) {
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering if (setsockopt(m->notify_watch.fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->notify_watch.fd, &ev) < 0) {
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering log_error("Failed to add notification socket fd to epoll: %m");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering m->notify_socket = strdup(sa.un.sun_path);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering log_debug("Using notification socket %s", m->notify_socket);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poetteringstatic int manager_jobs_in_progress_mod_timer(Manager *m) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering its.it_value.tv_sec = JOBS_IN_PROGRESS_WAIT_SEC;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering its.it_interval.tv_sec = JOBS_IN_PROGRESS_PERIOD_SEC;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering if (timerfd_settime(m->jobs_in_progress_watch.fd, 0, &its, NULL) < 0)
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poetteringstatic int manager_watch_jobs_in_progress(Manager *m) {
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering if (m->jobs_in_progress_watch.type != WATCH_INVALID)
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering m->jobs_in_progress_watch.type = WATCH_JOBS_IN_PROGRESS;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering m->jobs_in_progress_watch.fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering log_error("Failed to create timerfd: %m");
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering r = manager_jobs_in_progress_mod_timer(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to set up timer for jobs progress watch: %s", strerror(-r));
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering ev.data.ptr = &m->jobs_in_progress_watch;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->jobs_in_progress_watch.fd, &ev) < 0) {
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering log_error("Failed to add jobs progress timer fd to epoll: %m");
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering log_debug("Set up jobs progress timerfd.");
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering close_nointr_nofail(m->jobs_in_progress_watch.fd);
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poetteringstatic void manager_unwatch_jobs_in_progress(Manager *m) {
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering if (m->jobs_in_progress_watch.type != WATCH_JOBS_IN_PROGRESS)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, m->jobs_in_progress_watch.fd, NULL) >= 0);
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt close_nointr_nofail(m->jobs_in_progress_watch.fd);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_debug("Closed jobs progress timerfd.");
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering#define CYLON_BUFFER_EXTRA (2*strlen(ANSI_RED_ON) + strlen(ANSI_HIGHLIGHT_RED_ON) + 2*strlen(ANSI_HIGHLIGHT_OFF))
51323288fc628a5cac50914df915545d685b793eLennart Poetteringstatic void draw_cylon(char buffer[], size_t buflen, unsigned width, unsigned pos) {
51323288fc628a5cac50914df915545d685b793eLennart Poettering assert(buflen >= CYLON_BUFFER_EXTRA + width + 1);
51323288fc628a5cac50914df915545d685b793eLennart Poettering assert(pos <= width+1); /* 0 or width+1 mean that the center light is behind the corner */
51323288fc628a5cac50914df915545d685b793eLennart Poettering memcpy(p, ANSI_RED_ON, strlen(ANSI_RED_ON));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering memcpy(p, ANSI_HIGHLIGHT_RED_ON, strlen(ANSI_HIGHLIGHT_RED_ON));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering memcpy(p, ANSI_HIGHLIGHT_OFF, strlen(ANSI_HIGHLIGHT_OFF));
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering memcpy(p, ANSI_RED_ON, strlen(ANSI_RED_ON));
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering memcpy(p, ANSI_HIGHLIGHT_OFF, strlen(ANSI_HIGHLIGHT_OFF));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic void manager_print_jobs_in_progress(Manager *m) {
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering print_nr = (m->jobs_in_progress_iteration / JOBS_IN_PROGRESS_PERIOD_DIVISOR) % m->n_running_jobs;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (j->state == JOB_RUNNING && counter++ == print_nr)
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering /* m->n_running_jobs must be consistent with the contents of m->jobs,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * so the above loop must have succeeded in finding j. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering cylon_pos = m->jobs_in_progress_iteration % 14;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering draw_cylon(cylon, sizeof(cylon), 6, cylon_pos);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (asprintf(&job_of_n, "(%u of %u) ", counter, m->n_running_jobs) < 0)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering manager_status_printf(m, true, cylon, "%sA %s job is running for %s",
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering strempty(job_of_n), job_type_to_string(j->type), unit_description(j->unit));
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poetteringstatic int manager_setup_time_change(Manager *m) {
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering assert(m->time_change_watch.type == WATCH_INVALID);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering /* Uses TFD_TIMER_CANCEL_ON_SET to get notifications whenever
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering * CLOCK_REALTIME makes a jump relative to CLOCK_MONOTONIC */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering m->time_change_watch.type = WATCH_TIME_CHANGE;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering m->time_change_watch.fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering log_error("Failed to create timerfd: %m");
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering /* We only care for the cancellation event, hence we set the
95d46fcaa4f27bc5e675e8de39ab3acc4732e39bTom Gundersen * timeout to the latest possible value. */
95d46fcaa4f27bc5e675e8de39ab3acc4732e39bTom Gundersen assert_cc(sizeof(time_t) == sizeof(TIME_T_MAX));
7588460aaf6bd33f6c9bd5645916cfd8a862e9c4Tom Gundersen if (timerfd_settime(m->time_change_watch.fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0) {
95d46fcaa4f27bc5e675e8de39ab3acc4732e39bTom Gundersen log_debug("Failed to set up TFD_TIMER_CANCEL_ON_SET, ignoring: %m");
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering close_nointr_nofail(m->time_change_watch.fd);
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->time_change_watch.fd, &ev) < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to add timer change fd to epoll: %m");
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering log_debug("Set up TFD_TIMER_CANCEL_ON_SET timerfd.");
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poetteringstatic int enable_special_signals(Manager *m) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Enable that we get SIGINT on control-alt-del. In containers
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering * this will fail with EPERM (older) or EINVAL (newer), so
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering * ignore that. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (reboot(RB_DISABLE_CAD) < 0 && errno != EPERM && errno != EINVAL)
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering log_warning("Failed to enable ctrl-alt-del handling: %m");
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Support systems without virtual console */
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering log_warning("Failed to open /dev/tty0: %m");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Enable that we get SIGWINCH on kbrequest */
931851e8e492a4d2715e22dcde50a5e7ccef4b49Lennart Poettering if (ioctl(fd, KDSIGACCEPT, SIGWINCH) < 0)
51323288fc628a5cac50914df915545d685b793eLennart Poettering log_warning("Failed to enable kbrequest handling: %s", strerror(errno));
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poetteringstatic int manager_setup_signals(Manager *m) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering /* We are not interested in SIGSTOP and friends. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering SIGUSR1, /* systemd/upstart: reconnect to D-Bus */
51323288fc628a5cac50914df915545d685b793eLennart Poettering SIGINT, /* Kernel sends us this on control-alt-del */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering SIGWINCH, /* Kernel sends us this on kbrequest (alt-arrowup) */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering SIGPWR, /* Some kernel drivers and upsd send us this on power failure */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering SIGRTMIN+0, /* systemd: start default.target */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering SIGRTMIN+1, /* systemd: isolate rescue.target */
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering SIGRTMIN+2, /* systemd: isolate emergency.target */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering SIGRTMIN+3, /* systemd: start halt.target */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering SIGRTMIN+4, /* systemd: start poweroff.target */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering SIGRTMIN+5, /* systemd: start reboot.target */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering SIGRTMIN+6, /* systemd: start kexec.target */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering SIGRTMIN+13, /* systemd: Immediate halt */
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering SIGRTMIN+14, /* systemd: Immediate poweroff */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering SIGRTMIN+15, /* systemd: Immediate reboot */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering SIGRTMIN+16, /* systemd: Immediate kexec */
51323288fc628a5cac50914df915545d685b793eLennart Poettering SIGRTMIN+20, /* systemd: enable status messages */
51323288fc628a5cac50914df915545d685b793eLennart Poettering SIGRTMIN+21, /* systemd: disable status messages */
51323288fc628a5cac50914df915545d685b793eLennart Poettering SIGRTMIN+22, /* systemd: set log level to LOG_DEBUG */
51323288fc628a5cac50914df915545d685b793eLennart Poettering SIGRTMIN+23, /* systemd: set log level to LOG_INFO */
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering SIGRTMIN+24, /* systemd: Immediate exit (--user only) */
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering SIGRTMIN+26, /* systemd: set log target to journal-or-kmsg */
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering SIGRTMIN+27, /* systemd: set log target to console */
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering SIGRTMIN+28, /* systemd: set log target to kmsg */
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering SIGRTMIN+29, /* systemd: set log target to syslog-or-kmsg */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering m->signal_watch.fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
966c66e34940001a40806142ecebaae61b478444Lennart Poettering if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->signal_watch.fd, &ev) < 0)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poetteringstatic void manager_strip_environment(Manager *m) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering /* Remove variables from the inherited set that are part of
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering * the container interface:
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering * http://www.freedesktop.org/wiki/Software/systemd/ContainerInterface */
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering strv_remove_prefix(m->environment, "container=");
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering strv_remove_prefix(m->environment, "container_");
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering /* Remove variables from the inherited set that are part of
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering * the initrd interface:
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering * http://www.freedesktop.org/wiki/Software/systemd/InitrdInterface */
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering strv_remove_prefix(m->environment, "RD_");
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering /* Drop invalid entries */
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poetteringint manager_new(SystemdRunningAs running_as, Manager **_m) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering assert(running_as < _SYSTEMD_RUNNING_AS_MAX);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering dual_timestamp_get(&m->userspace_timestamp);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering dual_timestamp_from_monotonic(&m->kernel_timestamp, 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering efi_get_boot_timestamps(&m->userspace_timestamp, &m->firmware_timestamp, &m->loader_timestamp);
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering m->name_data_slot = m->conn_data_slot = m->subscribed_data_slot = -1;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering m->exit_code = _MANAGER_EXIT_CODE_INVALID;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering m->default_controllers = strv_new("cpu", NULL);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (!(m->units = hashmap_new(string_hash_func, string_compare_func)))
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering if (!(m->jobs = hashmap_new(trivial_hash_func, trivial_compare_func)))
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering if (!(m->watch_pids = hashmap_new(trivial_hash_func, trivial_compare_func)))
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering if (!(m->cgroup_bondings = hashmap_new(string_hash_func, string_compare_func)))
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering if (!(m->watch_bus = hashmap_new(string_hash_func, string_compare_func)))
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering /* Try to connect to the busses, if possible. */
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt r = bus_init(m, running_as != SYSTEMD_SYSTEM);
51323288fc628a5cac50914df915545d685b793eLennart Poetteringstatic unsigned manager_dispatch_cleanup_queue(Manager *m) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering unsigned n = 0;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering while ((u = m->cleanup_queue)) {
7b9f7afcc04e80b77a2567b0750aa2cd03c1a1cdLennart Poettering GC_OFFSET_IN_PATH, /* This one is on the path we were traveling */
eee026a7ba16336b6493828a2a13ddc9908667ffLennart Poettering GC_OFFSET_GOOD, /* We still need this unit */
d0129ddb9fbb07bed7c8ea51b8031f824bf506fbLennart Poettering GC_OFFSET_BAD, /* We don't need this unit anymore */
51323288fc628a5cac50914df915545d685b793eLennart Poetteringstatic void unit_gc_sweep(Unit *u, unsigned gc_marker) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (u->gc_marker == gc_marker + GC_OFFSET_GOOD ||
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering u->gc_marker == gc_marker + GC_OFFSET_BAD ||
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering u->gc_marker == gc_marker + GC_OFFSET_IN_PATH)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering u->gc_marker = gc_marker + GC_OFFSET_IN_PATH;
966c66e34940001a40806142ecebaae61b478444Lennart Poettering SET_FOREACH(other, u->dependencies[UNIT_REFERENCED_BY], i) {
82bd6dddc4a363a9c3c6f41eb46eb171a80dca27Lennart Poettering if (other->gc_marker == gc_marker + GC_OFFSET_GOOD)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (other->gc_marker != gc_marker + GC_OFFSET_BAD)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering /* We were unable to find anything out about this entry, so
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering * let's investigate it later */
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering u->gc_marker = gc_marker + GC_OFFSET_UNSURE;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering /* We definitely know that this one is not useful anymore, so
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering * let's mark it for deletion */
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering u->gc_marker = gc_marker + GC_OFFSET_BAD;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering u->gc_marker = gc_marker + GC_OFFSET_GOOD;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poetteringstatic unsigned manager_dispatch_gc_queue(Manager *m) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering unsigned n = 0;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if ((m->n_in_gc_queue < GC_QUEUE_ENTRIES_MAX) &&
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering (m->gc_queue_timestamp + GC_QUEUE_USEC_MAX) > now(CLOCK_MONOTONIC)))
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (m->gc_marker + _GC_OFFSET_MAX <= _GC_OFFSET_MAX)
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering while ((u = m->gc_queue)) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering LIST_REMOVE(Unit, gc_queue, m->gc_queue, u);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (u->gc_marker == gc_marker + GC_OFFSET_BAD ||
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering u->gc_marker == gc_marker + GC_OFFSET_UNSURE) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering log_debug_unit(u->id, "Collecting %s", u->id);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering u->gc_marker = gc_marker + GC_OFFSET_BAD;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poetteringstatic void manager_clear_jobs_and_units(Manager *m) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering for (c = 0; c < _UNIT_TYPE_MAX; c++)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering /* If we reexecute ourselves, we keep the root cgroup
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering manager_shutdown_cgroup(m, m->exit_code != MANAGER_REEXECUTE);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering close_nointr_nofail(m->time_change_watch.fd);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering close_nointr_nofail(m->jobs_in_progress_watch.fd);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering for (i = 0; i < RLIMIT_NLIMITS; i++)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering /* Let's ask every type to load all units from disk/kernel
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering * that it might know */
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering for (c = 0; c < _UNIT_TYPE_MAX; c++)
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering if ((q = unit_vtable[c]->enumerate(m)) < 0)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering /* Then, let's set up their initial state. */
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering /* ignore aliases */
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if ((q = unit_coldplug(u)) < 0)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poetteringstatic void manager_build_unit_path_cache(Manager *m) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering m->unit_path_cache = set_new(string_hash_func, string_compare_func);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering log_error("Failed to allocate unit path cache.");
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering /* This simply builds a list of files we know exist, so that
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering * we don't always have to go to disk */
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering STRV_FOREACH(i, m->lookup_paths.unit_path) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering log_error("Failed to open directory %s: %m", *i);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering p = strjoin(streq(*i, "/") ? "" : *i, "/", de->d_name, NULL);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering log_error("Failed to build unit path cache: %s", strerror(-r));
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poetteringint manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering /* If we will deserialize make sure that during enumeration
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering * this is already known, so we increase the counter here
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering /* First, enumerate what we can from all config files */
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering /* Second, deserialize if there is something to deserialize */
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering q = manager_deserialize(m, serialization, fds);
931851e8e492a4d2715e22dcde50a5e7ccef4b49Lennart Poettering /* Any fds left? Find some unit which wants them. This is
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering * useful to allow container managers to pass some file
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering * descriptors to us pre-initialized. This enables
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering * socket-based activation of entire containers. */
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering /* Third, fire things up! */
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poetteringint manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool override, DBusError *e, Job **_ret) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (mode == JOB_ISOLATE && type != JOB_START) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering dbus_set_error(e, BUS_ERROR_INVALID_JOB_MODE, "Isolate is only valid for start.");
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (mode == JOB_ISOLATE && !unit->allow_isolate) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering dbus_set_error(e, BUS_ERROR_NO_ISOLATION, "Operation refused, unit may not be isolated.");
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering "Trying to enqueue job %s/%s/%s", unit->id,
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering job_type_to_string(type), job_mode_to_string(mode));
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering tr = transaction_new(mode == JOB_REPLACE_IRREVERSIBLY);
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering r = transaction_add_job_and_dependencies(tr, type, unit, NULL, true, override, false,
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering mode == JOB_IGNORE_DEPENDENCIES || mode == JOB_IGNORE_REQUIREMENTS,
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = transaction_activate(tr, m, mode, e);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering job_type_to_string(type), (unsigned) tr->anchor_job->id);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poetteringint manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, bool override, DBusError *e, Job **_ret) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = manager_load_unit(m, name, NULL, NULL, &unit);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return manager_add_job(m, type, unit, mode, override, e, _ret);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart PoetteringJob *manager_get_job(Manager *m, uint32_t id) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return hashmap_get(m->jobs, UINT32_TO_PTR(id));
7588460aaf6bd33f6c9bd5645916cfd8a862e9c4Tom GundersenUnit *manager_get_unit(Manager *m, const char *name) {
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poetteringunsigned manager_dispatch_load_queue(Manager *m) {
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering unsigned n = 0;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering /* Make sure we are not run recursively */
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering /* Dispatches the load queue. Takes a unit from the queue and
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering * tries to load its data until the queue is empty */
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering while ((u = m->load_queue)) {
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poetteringint manager_load_unit_prepare(Manager *m, const char *name, const char *path, DBusError *e, Unit **_ret) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering /* This will prepare the unit for loading, but not actually
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering * load anything from disk. */
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering dbus_set_error(e, BUS_ERROR_INVALID_PATH, "Path %s is not absolute.", path);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (t == _UNIT_TYPE_INVALID || !unit_name_is_valid(name, false)) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering dbus_set_error(e, BUS_ERROR_INVALID_NAME, "Unit name %s is not valid.", name);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering ret = unit_new(m, unit_vtable[t]->object_size);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if ((r = unit_add_name(ret, name)) < 0) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poetteringint manager_load_unit(Manager *m, const char *name, const char *path, DBusError *e, Unit **_ret) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering /* This will load the service information files, but not actually
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering * start any services or anything. */
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = manager_load_unit_prepare(m, name, path, e, _ret);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poetteringvoid manager_dump_jobs(Manager *s, FILE *f, const char *prefix) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poetteringvoid manager_dump_units(Manager *s, FILE *f, const char *prefix) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering const char *t;
7f220d94a938a99c77400fa0ca30485e269bae7cLennart Poettering /* No need to recurse. We're cancelling all jobs. */
7f220d94a938a99c77400fa0ca30485e269bae7cLennart Poettering job_finish_and_invalidate(j, JOB_CANCELED, false);
7f220d94a938a99c77400fa0ca30485e269bae7cLennart Poetteringunsigned manager_dispatch_run_queue(Manager *m) {
7f220d94a938a99c77400fa0ca30485e269bae7cLennart Poettering unsigned n = 0;
7f220d94a938a99c77400fa0ca30485e269bae7cLennart Poettering while ((j = m->run_queue)) {
7f220d94a938a99c77400fa0ca30485e269bae7cLennart Poetteringunsigned manager_dispatch_dbus_queue(Manager *m) {
7f220d94a938a99c77400fa0ca30485e269bae7cLennart Poettering unsigned n = 0;
7f220d94a938a99c77400fa0ca30485e269bae7cLennart Poettering while ((u = m->dbus_unit_queue)) {
7f220d94a938a99c77400fa0ca30485e269bae7cLennart Poettering while ((j = m->dbus_job_queue)) {
7f220d94a938a99c77400fa0ca30485e269bae7cLennart Poetteringstatic int manager_process_notify_fd(Manager *m) {
7f220d94a938a99c77400fa0ca30485e269bae7cLennart Poettering uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
7f220d94a938a99c77400fa0ca30485e269bae7cLennart Poettering n = recvmsg(m->notify_watch.fd, &msghdr, MSG_DONTWAIT);
7f220d94a938a99c77400fa0ca30485e269bae7cLennart Poettering if (msghdr.msg_controllen < CMSG_LEN(sizeof(struct ucred)) ||
7f220d94a938a99c77400fa0ca30485e269bae7cLennart Poettering control.cmsghdr.cmsg_level != SOL_SOCKET ||
7f220d94a938a99c77400fa0ca30485e269bae7cLennart Poettering control.cmsghdr.cmsg_type != SCM_CREDENTIALS ||
7f220d94a938a99c77400fa0ca30485e269bae7cLennart Poettering control.cmsghdr.cmsg_len != CMSG_LEN(sizeof(struct ucred))) {
7f220d94a938a99c77400fa0ca30485e269bae7cLennart Poettering log_warning("Received notify message without credentials. Ignoring.");
a150ff5e4e2481eb28d6ed6e0d3e176623e25f5aLennart Poettering ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr);
a150ff5e4e2481eb28d6ed6e0d3e176623e25f5aLennart Poettering u = hashmap_get(m->watch_pids, LONG_TO_PTR(ucred->pid));
a150ff5e4e2481eb28d6ed6e0d3e176623e25f5aLennart Poettering log_warning("Cannot find unit for notify message of PID %lu.", (unsigned long) ucred->pid);
a150ff5e4e2481eb28d6ed6e0d3e176623e25f5aLennart Poettering log_debug_unit(u->id, "Got notification message for unit %s", u->id);
a150ff5e4e2481eb28d6ed6e0d3e176623e25f5aLennart Poettering UNIT_VTABLE(u)->notify_message(u, ucred->pid, tags);
a150ff5e4e2481eb28d6ed6e0d3e176623e25f5aLennart Poetteringstatic int manager_dispatch_sigchld(Manager *m) {
a150ff5e4e2481eb28d6ed6e0d3e176623e25f5aLennart Poettering /* First we call waitd() for a PID and do not reap the
a150ff5e4e2481eb28d6ed6e0d3e176623e25f5aLennart Poettering * zombie. That way we can still access /proc/$PID for
a150ff5e4e2481eb28d6ed6e0d3e176623e25f5aLennart Poettering * it while it is a zombie. */
a150ff5e4e2481eb28d6ed6e0d3e176623e25f5aLennart Poettering if (waitid(P_ALL, 0, &si, WEXITED|WNOHANG|WNOWAIT) < 0) {
a150ff5e4e2481eb28d6ed6e0d3e176623e25f5aLennart Poettering if (si.si_code == CLD_EXITED || si.si_code == CLD_KILLED || si.si_code == CLD_DUMPED) {
a150ff5e4e2481eb28d6ed6e0d3e176623e25f5aLennart Poettering log_debug("Got SIGCHLD for process %lu (%s)", (unsigned long) si.si_pid, strna(name));
a150ff5e4e2481eb28d6ed6e0d3e176623e25f5aLennart Poettering /* Let's flush any message the dying child might still
a150ff5e4e2481eb28d6ed6e0d3e176623e25f5aLennart Poettering * have queued for us. This ensures that the process
a150ff5e4e2481eb28d6ed6e0d3e176623e25f5aLennart Poettering * still exists in /proc so that we can figure out
593f665cd5ffddbaa3ddbe9d963af923ed1cc5dcLennart Poettering * which cgroup and hence unit it belongs to. */
593f665cd5ffddbaa3ddbe9d963af923ed1cc5dcLennart Poettering /* And now figure out the unit this belongs to */
593f665cd5ffddbaa3ddbe9d963af923ed1cc5dcLennart Poettering u = hashmap_get(m->watch_pids, LONG_TO_PTR(si.si_pid));
593f665cd5ffddbaa3ddbe9d963af923ed1cc5dcLennart Poettering /* And now, we actually reap the zombie. */
593f665cd5ffddbaa3ddbe9d963af923ed1cc5dcLennart Poettering if (waitid(P_PID, si.si_pid, &si, WEXITED) < 0) {
593f665cd5ffddbaa3ddbe9d963af923ed1cc5dcLennart Poettering if (si.si_code != CLD_EXITED && si.si_code != CLD_KILLED && si.si_code != CLD_DUMPED)
593f665cd5ffddbaa3ddbe9d963af923ed1cc5dcLennart Poettering log_debug("Child %lu died (code=%s, status=%i/%s)",
593f665cd5ffddbaa3ddbe9d963af923ed1cc5dcLennart Poettering ? exit_status_to_string(si.si_status, EXIT_STATUS_FULL)
a150ff5e4e2481eb28d6ed6e0d3e176623e25f5aLennart Poettering "Child %lu belongs to %s", (long unsigned) si.si_pid, u->id);
a150ff5e4e2481eb28d6ed6e0d3e176623e25f5aLennart Poettering hashmap_remove(m->watch_pids, LONG_TO_PTR(si.si_pid));
a150ff5e4e2481eb28d6ed6e0d3e176623e25f5aLennart Poettering UNIT_VTABLE(u)->sigchld_event(u, si.si_pid, si.si_code, si.si_status);
a150ff5e4e2481eb28d6ed6e0d3e176623e25f5aLennart Poetteringstatic int manager_start_target(Manager *m, const char *name, JobMode mode) {
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering log_debug_unit(name, "Activating special unit %s", name);
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering r = manager_add_job_by_name(m, JOB_START, name, mode, true, &error, NULL);
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering "Failed to enqueue %s job: %s", name, bus_error(&error, r));
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poetteringstatic int manager_process_signal_fd(Manager *m) {
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering n = read(m->signal_watch.fd, &sfsi, sizeof(sfsi));
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering if (n != sizeof(sfsi)) {
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering log_debug("Received SIG%s from PID %lu (%s).",
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering log_debug("Received SIG%s.", signal_to_string(sfsi.ssi_signo));
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering /* This is for compatibility with the
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering * original sysvinit */
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering /* Fall through */
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE);
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering /* Run the exit target if there is one, if not, just exit. */
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering if (manager_start_target(m, SPECIAL_EXIT_TARGET, JOB_REPLACE) < 0) {
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering manager_start_target(m, SPECIAL_KBREQUEST_TARGET, JOB_REPLACE);
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering /* This is a nop on non-init */
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering manager_start_target(m, SPECIAL_SIGPWR_TARGET, JOB_REPLACE);
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering /* This is a nop on non-init */
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering u = manager_get_unit(m, SPECIAL_DBUS_SERVICE);
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering if (!u || UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) {
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering log_info("Trying to reconnect to bus...");
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering if (!u || !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u))) {
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering manager_start_target(m, SPECIAL_DBUS_SERVICE, JOB_REPLACE);
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering if (!(f = open_memstream(&dump, &size))) {
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering log_warning("Failed to allocate memory stream.");
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering log_warning("Failed to write status stream");
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering /* Starting SIGRTMIN+0 */
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering static const char * const target_table[] = {
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering /* Starting SIGRTMIN+13, so that target halt and system halt are 10 apart */
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering static const ManagerExitCode code_table[] = {
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering if ((int) sfsi.ssi_signo >= SIGRTMIN+0 &&
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering (int) sfsi.ssi_signo < SIGRTMIN+(int) ELEMENTSOF(target_table)) {
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering int idx = (int) sfsi.ssi_signo - SIGRTMIN;
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering manager_start_target(m, target_table[idx],
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering (idx == 1 || idx == 2) ? JOB_ISOLATE : JOB_REPLACE);
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering if ((int) sfsi.ssi_signo >= SIGRTMIN+13 &&
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering (int) sfsi.ssi_signo < SIGRTMIN+13+(int) ELEMENTSOF(code_table)) {
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering m->exit_code = code_table[sfsi.ssi_signo - SIGRTMIN - 13];
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering log_debug("Enabling showing of status.");
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering log_debug("Disabling showing of status.");
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering log_notice("Setting log level to debug.");
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering log_notice("Setting log level to info.");
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering /* This is a nop on init */
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering log_notice("Setting log target to journal-or-kmsg.");
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering log_notice("Setting log target to console.");
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering log_notice("Setting log target to kmsg.");
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering log_set_target(LOG_TARGET_SYSLOG_OR_KMSG);
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering log_notice("Setting log target to syslog-or-kmsg.");
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering log_warning("Got unhandled signal <%s>.", signal_to_string(sfsi.ssi_signo));
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poetteringstatic int process_event(Manager *m, struct epoll_event *ev) {
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering /* An incoming signal? */
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering if ((r = manager_process_signal_fd(m)) < 0)
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering /* An incoming daemon notification event? */
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering if ((r = manager_process_notify_fd(m)) < 0)
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering /* Some fd event, to be dispatched to the units */
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering UNIT_VTABLE(w->data.unit)->fd_event(w->data.unit, w->fd, ev->events, w);
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering /* Some timer event, to be dispatched to the units */
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering if (k != sizeof(v)) {
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering if (k < 0 && (errno == EINTR || errno == EAGAIN))
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering log_error("Failed to read timer event counter: %s", k < 0 ? strerror(-k) : "Short read");
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering UNIT_VTABLE(w->data.unit)->timer_event(w->data.unit, v, w);
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering /* Some mount table change, intended for the mount subsystem */
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering /* Some swap table change, intended for the swap subsystem */
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering /* Some notification from udev, intended for the device subsystem */
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering "MESSAGE=Time has been changed",
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering /* Restart the watch */
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering close_nointr_nofail(m->time_change_watch.fd);
e40f0647b48b57af5e874501ad9c05dc459108deLennart Poettering /* not interested in the data */
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering assert_not_reached("Unknown epoll event type.");
97e5d693c04e50605d438af1c8a965fd2963bbe9Lennart Poettering RATELIMIT_DEFINE(rl, 1*USEC_PER_SEC, 50000);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Release the path cache */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* There might still be some zombies hanging around from
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * before we were exec()'ed. Leat's reap them */
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering while (m->exit_code == MANAGER_RUNNING) {
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering if (m->runtime_watchdog > 0 && m->running_as == SYSTEMD_SYSTEM)
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt /* Yay, something is going seriously wrong, pause a little */
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering log_warning("Looping too fast. Throttling execution a little.");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (manager_dispatch_cleanup_queue(m) > 0)
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt /* Sleep for half the watchdog time */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (m->runtime_watchdog > 0 && m->running_as == SYSTEMD_SYSTEM) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering wait_msec = (int) (m->runtime_watchdog / 2 / USEC_PER_MSEC);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering n = epoll_wait(m->epoll_fd, &event, 1, wait_msec);
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt } else if (n == 0)
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poetteringint manager_load_unit_from_dbus_path(Manager *m, const char *s, DBusError *e, Unit **_u) {
return -EINVAL;
return -ENOMEM;
free(n);
*_u = u;
Job *j;
unsigned id;
assert(m);
assert(s);
return -EINVAL;
return -ENOENT;
*_j = j;
#ifdef HAVE_AUDIT
int audit_fd;
if (audit_fd < 0)
if (m->n_reloading > 0)
free(p);
if (m->n_reloading > 0)
if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) {
goto finish;
log_oom();
goto finish;
errno = 0;
goto finish;
if (fd >= 0)
Manager *m,
const char *name,
const char* old_owner,
const char *new_owner) {
Unit *u;
assert(m);
Manager *m,
const char *name,
Unit *u;
assert(m);
int fd;
FILE *f;
if (!path)
return -ENOMEM;
if (fd < 0) {
return -errno;
return -errno;
*_f = f;
Iterator i;
Unit *u;
assert(m);
assert(f);
m->n_reloading ++;
if (!in_initrd()) {
if (ce)
if (u->id != t)
if (!unit_can_serialize(u))
m->n_reloading --;
m->n_reloading --;
if (ferror(f))
return -EIO;
assert(m);
assert(f);
m->n_reloading ++;
if (feof(f))
r = -errno;
goto finish;
uint32_t n;
m->n_installed_jobs += n;
uint32_t n;
m->n_failed_jobs += n;
if (!uce) {
r = -ENOMEM;
goto finish;
r = -ENOMEM;
goto finish;
m->environment = e;
Unit *u;
if (feof(f))
r = -errno;
goto finish;
goto finish;
goto finish;
if (ferror(f)) {
r = -EIO;
goto finish;
m->n_reloading --;
Unit *u;
Iterator i;
assert(m);
FILE *f;
assert(m);
r = manager_open_serialization(m, &f);
m->n_reloading ++;
if (!fds) {
m->n_reloading --;
r = -ENOMEM;
goto finish;
m->n_reloading --;
goto finish;
m->n_reloading --;
r = -errno;
goto finish;
q = lookup_paths_init(
q = manager_enumerate(m);
fclose(f);
f = NULL;
q = manager_coldplug(m);
m->n_reloading--;
fclose(f);
if (fds)
Unit *u;
assert(m);
return !!u->job;
Unit *u;
Iterator i;
assert(m);
Unit *u;
assert(m);
return unit_pending_inactive(u);
char userspace[FORMAT_TIMESPAN_MAX], initrd[FORMAT_TIMESPAN_MAX], kernel[FORMAT_TIMESPAN_MAX], sum[FORMAT_TIMESPAN_MAX];
assert(m);
if (m->n_running_jobs == 0)
m->confirm_spawn = false;
if (!log_on_console())
NULL);
initrd_usec = 0;
if (!log_on_console())
NULL);
if (!log_on_console())
NULL);
bus_broadcast_finished(m, firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec);
sd_notifyf(false,
assert(m);
if (*generator)
return log_oom();
p, strerror(-r));
free(p);
return log_oom();
if (!mkdtemp(p)) {
free(p);
return -errno;
*generator = p;
assert(m);
if (!*generator)
const char *generator_path;
mode_t u;
assert(m);
goto finish;
goto finish;
goto finish;
umask(u);
closedir(d);
assert(m);
if (!*generator)
assert(m);
assert(m);
return -ENOMEM;
m->default_controllers = l;
assert(m);
for (i = 0; i < RLIMIT_NLIMITS; i++) {
if (!default_rlimit[i])
if (!m->rlimit[i])
return -ENOMEM;
Unit *u;
assert(m);
log_open();
assert(m);
m->show_status = b;
assert(m);
if (m->show_status)
return plymouth_running();
void manager_status_printf(Manager *m, bool ephemeral, const char *status, const char *format, ...) {
if (!manager_get_show_status(m))
if (!manager_is_booting_or_shutting_down(m))
assert(w);