#include "dbus-job.h"
#include "missing.h"
#include "path-lookup.h"
+#include "special.h"
/* As soon as 16 units are in our GC queue, make sure to run a gc sweep */
#define GC_QUEUE_ENTRIES_MAX 16
struct sockaddr_un un;
} sa;
struct epoll_event ev;
- char *ne[2], **t;
int one = 1;
assert(m);
if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->notify_watch.fd, &ev) < 0)
return -errno;
- if (asprintf(&ne[0], "NOTIFY_SOCKET=@%s", sa.un.sun_path+1) < 0)
+ if (!(m->notify_socket = strdup(sa.un.sun_path+1)))
return -ENOMEM;
- ne[1] = NULL;
- t = strv_env_merge(m->environment, ne, NULL);
- free(ne[0]);
-
- if (!t)
- return -ENOMEM;
-
- strv_free(m->environment);
- m->environment = t;
-
return 0;
}
assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
assert_se(sigemptyset(&mask) == 0);
- assert_se(sigaddset(&mask, SIGCHLD) == 0);
- assert_se(sigaddset(&mask, SIGTERM) == 0);
- assert_se(sigaddset(&mask, SIGHUP) == 0);
- assert_se(sigaddset(&mask, SIGUSR1) == 0);
- assert_se(sigaddset(&mask, SIGUSR2) == 0);
- assert_se(sigaddset(&mask, SIGINT) == 0); /* Kernel sends us this on control-alt-del */
- assert_se(sigaddset(&mask, SIGWINCH) == 0); /* Kernel sends us this on kbrequest (alt-arrowup) */
- assert_se(sigaddset(&mask, SIGPWR) == 0); /* Some kernel drivers and upsd send us this on power failure */
+
+ sigset_add_many(&mask,
+ SIGCHLD, /* Child died */
+ SIGTERM, /* Reexecute daemon */
+ SIGHUP, /* Reload configuration */
+ SIGUSR1, /* systemd/upstart: reconnect to D-Bus */
+ SIGUSR2, /* systemd: dump status */
+ SIGINT, /* Kernel sends us this on control-alt-del */
+ SIGWINCH, /* Kernel sends us this on kbrequest (alt-arrowup) */
+ SIGPWR, /* Some kernel drivers and upsd send us this on power failure */
+ SIGRTMIN+0, /* systemd: start default.target */
+ SIGRTMIN+1, /* systemd: start rescue.target */
+ SIGRTMIN+2, /* systemd: isolate emergency.target */
+ SIGRTMIN+3, /* systemd: start halt.target */
+ SIGRTMIN+4, /* systemd: start poweroff.target */
+ SIGRTMIN+5, /* systemd: start reboot.target */
+ -1);
assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
m->signal_watch.type = WATCH_SIGNAL;
int manager_new(ManagerRunningAs running_as, bool confirm_spawn, Manager **_m) {
Manager *m;
int r = -ENOMEM;
+ char *p;
assert(_m);
assert(running_as >= 0);
m->confirm_spawn = confirm_spawn;
m->name_data_slot = -1;
m->exit_code = _MANAGER_EXIT_CODE_INVALID;
+ m->pin_cgroupfs_fd = -1;
m->signal_watch.fd = m->mount_watch.fd = m->udev_watch.fd = m->epoll_fd = m->dev_autofs_fd = -1;
m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */
(r = bus_init_api(m)) < 0)
goto fail;
+ if (asprintf(&p, "%s/%s", m->cgroup_mount_point, m->cgroup_hierarchy) < 0) {
+ r = -ENOMEM;
+ goto fail;
+ }
+
+ m->pin_cgroupfs_fd = open(p, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY|O_NONBLOCK);
+ free(p);
+
*_m = m;
return 0;
if (m->notify_watch.fd >= 0)
close_nointr_nofail(m->notify_watch.fd);
+ free(m->notify_socket);
+
lookup_paths_free(&m->lookup_paths);
strv_free(m->environment);
free(m->cgroup_controller);
free(m->cgroup_hierarchy);
+ free(m->cgroup_mount_point);
hashmap_free(m->cgroup_bondings);
+ if (m->pin_cgroupfs_fd >= 0)
+ close_nointr_nofail(m->pin_cgroupfs_fd);
+
free(m);
}
continue;
}
- char_array_0(buf);
+ assert((size_t) n < sizeof(buf));
+ buf[n] = 0;
if (!(tags = strv_split(buf, "\n\r")))
return -ENOMEM;
log_debug("Got notification message for unit %s", u->meta.id);
if (UNIT_VTABLE(u)->notify_message)
- UNIT_VTABLE(u)->notify_message(u, tags);
+ UNIT_VTABLE(u)->notify_message(u, ucred->pid, tags);
strv_free(tags);
}
return 0;
}
-static int manager_start_target(Manager *m, const char *name) {
+static int manager_start_target(Manager *m, const char *name, JobMode mode) {
int r;
- if ((r = manager_add_job_by_name(m, JOB_START, name, JOB_REPLACE, true, NULL)) < 0)
+ if ((r = manager_add_job_by_name(m, JOB_START, name, mode, true, NULL)) < 0)
log_error("Failed to enqueue %s job: %s", name, strerror(-r));
return r;
case SIGINT:
if (m->running_as == MANAGER_INIT) {
- manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET);
+ 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_SERVICE) < 0) {
+ if (manager_start_target(m, SPECIAL_EXIT_SERVICE, JOB_REPLACE) < 0) {
m->exit_code = MANAGER_EXIT;
return 0;
}
case SIGWINCH:
if (m->running_as == MANAGER_INIT)
- manager_start_target(m, SPECIAL_KBREQUEST_TARGET);
+ manager_start_target(m, SPECIAL_KBREQUEST_TARGET, JOB_REPLACE);
/* This is a nop on non-init */
break;
case SIGPWR:
if (m->running_as == MANAGER_INIT)
- manager_start_target(m, SPECIAL_SIGPWR_TARGET);
+ manager_start_target(m, SPECIAL_SIGPWR_TARGET, JOB_REPLACE);
/* This is a nop on non-init */
break;
if (!u || !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u))) {
log_info("Loading D-Bus service...");
- manager_start_target(m, SPECIAL_DBUS_SERVICE);
+ manager_start_target(m, SPECIAL_DBUS_SERVICE, JOB_REPLACE);
}
break;
m->exit_code = MANAGER_RELOAD;
break;
- default:
+ default: {
+ static const char * const table[] = {
+ [0] = SPECIAL_DEFAULT_TARGET,
+ [1] = SPECIAL_RESCUE_TARGET,
+ [2] = SPECIAL_EMERGENCY_SERVICE,
+ [3] = SPECIAL_HALT_TARGET,
+ [4] = SPECIAL_POWEROFF_TARGET,
+ [5] = SPECIAL_REBOOT_TARGET
+ };
+
+ if ((int) sfsi.ssi_signo >= SIGRTMIN+0 &&
+ (int) sfsi.ssi_signo < SIGRTMIN+(int) ELEMENTSOF(table)) {
+ manager_start_target(m, table[sfsi.ssi_signo - SIGRTMIN],
+ sfsi.ssi_signo == 2 ? JOB_ISOLATE : JOB_REPLACE);
+ break;
+ }
+
log_info("Got unhandled signal <%s>.", strsignal(sfsi.ssi_signo));
}
+ }
}
if (sigchld)