return 0;
}
+#define RTSIG_IF_AVAILABLE(signum) (signum <= SIGRTMAX ? signum : -1)
+
static int manager_setup_signals(Manager *m) {
struct sigaction sa = {
.sa_handler = SIG_DFL,
/* .. one free signal here ... */
-#if !defined(__hppa64__) && !defined(__hppa__)
- /* Apparently Linux on hppa has fewer RT
- * signals (SIGRTMAX is SIGRTMIN+25 there),
- * hence let's not try to make use of them
- * here. Since these commands are accessible
- * by different means and only really a safety
- * net, the missing functionality on hppa
- * shouldn't matter. */
-
- SIGRTMIN+26, /* systemd: set log target to journal-or-kmsg */
- SIGRTMIN+27, /* systemd: set log target to console */
- SIGRTMIN+28, /* systemd: set log target to kmsg */
- SIGRTMIN+29, /* systemd: set log target to syslog-or-kmsg (obsolete) */
+ /* Apparently Linux on hppa had fewer RT signals until v3.18,
+ * SIGRTMAX was SIGRTMIN+25, and then SIGRTMIN was lowered,
+ * see commit v3.17-7614-g1f25df2eff.
+ *
+ * We cannot unconditionally make use of those signals here,
+ * so let's use a runtime check. Since these commands are
+ * accessible by different means and only really a safety
+ * net, the missing functionality on hppa shouldn't matter.
+ */
+
+ RTSIG_IF_AVAILABLE(SIGRTMIN+26), /* systemd: set log target to journal-or-kmsg */
+ RTSIG_IF_AVAILABLE(SIGRTMIN+27), /* systemd: set log target to console */
+ RTSIG_IF_AVAILABLE(SIGRTMIN+28), /* systemd: set log target to kmsg */
+ RTSIG_IF_AVAILABLE(SIGRTMIN+29), /* systemd: set log target to syslog-or-kmsg (obsolete) */
/* ... one free signal here SIGRTMIN+30 ... */
-#endif
-1);
assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
}
int manager_new(UnitFileScope scope, unsigned test_run_flags, Manager **_m) {
- Manager *m;
+ _cleanup_(manager_freep) Manager *m = NULL;
int r;
assert(_m);
r = manager_default_environment(m);
if (r < 0)
- goto fail;
+ return r;
r = hashmap_ensure_allocated(&m->units, &string_hash_ops);
if (r < 0)
- goto fail;
+ return r;
r = hashmap_ensure_allocated(&m->jobs, NULL);
if (r < 0)
- goto fail;
+ return r;
r = hashmap_ensure_allocated(&m->cgroup_unit, &path_hash_ops);
if (r < 0)
- goto fail;
+ return r;
r = hashmap_ensure_allocated(&m->watch_bus, &string_hash_ops);
if (r < 0)
- goto fail;
+ return r;
- r = sd_event_default(&m->event);
+ r = manager_setup_prefix(m);
if (r < 0)
- goto fail;
+ return r;
- r = manager_setup_run_queue(m);
- if (r < 0)
- goto fail;
+ m->udev = udev_new();
+ if (!m->udev)
+ return -ENOMEM;
- r = manager_setup_signals(m);
+ r = sd_event_default(&m->event);
if (r < 0)
- goto fail;
+ return r;
- r = manager_setup_cgroup(m);
+ r = manager_setup_run_queue(m);
if (r < 0)
- goto fail;
+ return r;
- r = manager_setup_time_change(m);
- if (r < 0)
- goto fail;
+ if (test_run_flags == MANAGER_TEST_RUN_MINIMAL) {
+ m->cgroup_root = strdup("");
+ if (!m->cgroup_root)
+ return -ENOMEM;
+ } else {
+ r = manager_setup_signals(m);
+ if (r < 0)
+ return r;
- r = manager_setup_sigchld_event_source(m);
- if (r < 0)
- goto fail;
+ r = manager_setup_cgroup(m);
+ if (r < 0)
+ return r;
- m->udev = udev_new();
- if (!m->udev) {
- r = -ENOMEM;
- goto fail;
- }
+ r = manager_setup_time_change(m);
+ if (r < 0)
+ return r;
- r = manager_setup_prefix(m);
- if (r < 0)
- goto fail;
+ r = manager_setup_sigchld_event_source(m);
+ if (r < 0)
+ return r;
+ }
if (MANAGER_IS_SYSTEM(m) && test_run_flags == 0) {
r = mkdir_label("/run/systemd/units", 0755);
if (r < 0 && r != -EEXIST)
- goto fail;
+ return r;
}
m->taint_usr =
/* Note that we do not set up the notify fd here. We do that after deserialization,
* since they might have gotten serialized across the reexec. */
- *_m = m;
- return 0;
+ *_m = TAKE_PTR(m);
-fail:
- manager_free(m);
- return r;
+ return 0;
}
static int manager_setup_notify(Manager *m) {
if (r < 0)
return log_error_errno(errno, "SO_PASSCRED failed: %m");
- m->notify_fd = fd;
- fd = -1;
+ m->notify_fd = TAKE_FD(fd);
log_debug("Using notification socket %s", m->notify_socket);
}
return hashmap_get(m->units, name);
}
+static int manager_dispatch_target_deps_queue(Manager *m) {
+ Unit *u;
+ unsigned k;
+ int r = 0;
+
+ static const UnitDependency deps[] = {
+ UNIT_REQUIRED_BY,
+ UNIT_REQUISITE_OF,
+ UNIT_WANTED_BY,
+ UNIT_BOUND_BY
+ };
+
+ assert(m);
+
+ while ((u = m->target_deps_queue)) {
+ assert(u->in_target_deps_queue);
+
+ LIST_REMOVE(target_deps_queue, u->manager->target_deps_queue, u);
+ u->in_target_deps_queue = false;
+
+ for (k = 0; k < ELEMENTSOF(deps); k++) {
+ Unit *target;
+ Iterator i;
+ void *v;
+
+ HASHMAP_FOREACH_KEY(v, target, u->dependencies[deps[k]], i) {
+ r = unit_add_default_target_dependency(u, target);
+ if (r < 0)
+ return r;
+ }
+ }
+ }
+
+ return r;
+}
+
unsigned manager_dispatch_load_queue(Manager *m) {
Unit *u;
unsigned n = 0;
}
m->dispatching_load_queue = false;
+
+ /* Dispatch the units waiting for their target dependencies to be added now, as all targets that we know about
+ * should be loaded and have aliases resolved */
+ (void) manager_dispatch_target_deps_queue(m);
+
return n;
}
sd_bus_error *e,
Unit **_ret) {
+ _cleanup_(unit_freep) Unit *cleanup_ret = NULL;
Unit *ret;
UnitType t;
int r;
return 1;
}
- ret = unit_new(m, unit_vtable[t]->object_size);
+ ret = cleanup_ret = unit_new(m, unit_vtable[t]->object_size);
if (!ret)
return -ENOMEM;
if (path) {
ret->fragment_path = strdup(path);
- if (!ret->fragment_path) {
- unit_free(ret);
+ if (!ret->fragment_path)
return -ENOMEM;
- }
}
r = unit_add_name(ret, name);
- if (r < 0) {
- unit_free(ret);
+ if (r < 0)
return r;
- }
unit_add_to_load_queue(ret);
unit_add_to_dbus_queue(ret);
unit_add_to_gc_queue(ret);
*_ret = ret;
+ cleanup_ret = NULL;
return 0;
}
f = safe_fclose(f);
- *ret = dump;
- dump = NULL;
+ *ret = TAKE_PTR(dump);
return 0;
}
case SIGTERM:
if (MANAGER_IS_SYSTEM(m)) {
- /* This is for compatibility with the
- * original sysvinit */
+ /* This is for compatibility with the original sysvinit */
r = verify_run_space_and_log("Refusing to reexecute");
if (r >= 0)
m->exit_code = MANAGER_REEXECUTE;
break;
case SIGWINCH:
+ /* This is a nop on non-init */
if (MANAGER_IS_SYSTEM(m))
manager_start_target(m, SPECIAL_KBREQUEST_TARGET, JOB_REPLACE);
- /* This is a nop on non-init */
break;
case SIGPWR:
+ /* This is a nop on non-init */
if (MANAGER_IS_SYSTEM(m))
manager_start_target(m, SPECIAL_SIGPWR_TARGET, JOB_REPLACE);
- /* This is a nop on non-init */
break;
case SIGUSR1:
-
if (manager_dbus_is_running(m, false)) {
log_info("Trying to reconnect to bus...");
exec_runtime_vacuum(m);
+ assert(m->n_reloading > 0);
+ m->n_reloading--;
+
/* It might be safe to log to the journal now and connect to dbus */
manager_recheck_journal(m);
manager_recheck_dbus(m);
if (q < 0 && r >= 0)
r = q;
- assert(m->n_reloading > 0);
- m->n_reloading--;
-
m->send_reloading_done = true;
return r;
* connection of the API bus). That's because the system bus after all runs as service of the system instance,
* while in the user instance we can assume it's already there. */
+ if (MANAGER_IS_RELOADING(m))
+ return; /* don't check while we are reloading… */
+
if (manager_dbus_is_running(m, false)) {
(void) bus_init_api(m);
if (getpid_cached() != 1)
return;
+ /* Don't check this while we are reloading, things might still change */
+ if (MANAGER_IS_RELOADING(m))
+ return;
+
/* The journal is fully and entirely up? If so, let's permit logging to it, if that's configured. If the
* journal is down, don't ever log to it, otherwise we might end up deadlocking ourselves as we might trigger
* an activation ourselves we can't fulfill. */