assert(m);
assert_cc(sizeof(time_t) == sizeof(TIME_T_MAX));
+ if (m->test_run)
+ return 0;
+
/* Uses TFD_TIMER_CANCEL_ON_SET to get notifications whenever
* CLOCK_REALTIME makes a jump relative to CLOCK_MONOTONIC */
assert(m);
+ if (m->test_run)
+ return 0;
+
/* We are not interested in SIGSTOP and friends. */
assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
return 0;
}
-int manager_new(SystemdRunningAs running_as, Manager **_m) {
+int manager_new(SystemdRunningAs running_as, bool test_run, Manager **_m) {
Manager *m;
int r;
return -ENOMEM;
#ifdef ENABLE_EFI
- if (detect_container(NULL) <= 0)
+ if (running_as == SYSTEMD_SYSTEM && detect_container(NULL) <= 0)
boot_timestamps(&m->userspace_timestamp, &m->firmware_timestamp, &m->loader_timestamp);
#endif
m->running_as = running_as;
m->exit_code = _MANAGER_EXIT_CODE_INVALID;
+ m->default_timer_accuracy_usec = USEC_PER_MINUTE;
m->idle_pipe[0] = m->idle_pipe[1] = m->idle_pipe[2] = m->idle_pipe[3] = -1;
m->pin_cgroupfs_fd = m->notify_fd = m->signal_fd = m->time_change_fd = m->dev_autofs_fd = m->private_listen_fd = m->kdbus_fd = -1;
m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */
+ m->test_run = test_run;
+
r = manager_default_environment(m);
if (r < 0)
goto fail;
if (r < 0)
goto fail;
+ r = set_ensure_allocated(&m->startup_units, trivial_hash_func, trivial_compare_func);
+ if (r < 0)
+ goto fail;
+
r = set_ensure_allocated(&m->failed_units, trivial_hash_func, trivial_compare_func);
if (r < 0)
goto fail;
static int manager_setup_notify(Manager *m) {
int r;
+ if (m->test_run)
+ return 0;
+
if (m->notify_fd < 0) {
_cleanup_close_ int fd = -1;
union {
strncpy(sa.un.sun_path, m->notify_socket, sizeof(sa.un.sun_path)-1);
r = bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path));
if (r < 0) {
- log_error("bind() failed: %m");
+ log_error("bind(@%s) failed: %m", sa.un.sun_path+1);
return -errno;
}
static int manager_setup_kdbus(Manager *m) {
#ifdef ENABLE_KDBUS
_cleanup_free_ char *p = NULL;
-#endif
-#ifdef ENABLE_KDBUS
assert(m);
- if (m->kdbus_fd >= 0)
+ if (m->test_run || m->kdbus_fd >= 0)
return 0;
m->kdbus_fd = bus_kernel_create_bus(m->running_as == SYSTEMD_SYSTEM ? "system" : "user", m->running_as == SYSTEMD_SYSTEM, &p);
assert(m);
+ if (m->test_run)
+ return 0;
+
try_bus_connect =
m->kdbus_fd >= 0 ||
reexecuting ||
hashmap_free(m->watch_pids2);
hashmap_free(m->watch_bus);
+ set_free(m->startup_units);
set_free(m->failed_units);
sd_event_source_unref(m->signal_event_source);
r = lookup_paths_init(
&m->lookup_paths, m->running_as, true,
+ NULL,
m->generator_unit_path,
m->generator_unit_path_early,
m->generator_unit_path_late);
dual_timestamp_get(&m->units_load_finish_timestamp);
/* Second, deserialize if there is something to deserialize */
- if (serialization) {
- q = manager_deserialize(m, serialization, fds);
- if (q < 0)
- r = q;
- }
+ if (serialization)
+ r = manager_deserialize(m, serialization, fds);
/* Any fds left? Find some unit which wants them. This is
* useful to allow container managers to pass some file
* socket-based activation of entire containers. */
if (fdset_size(fds) > 0) {
q = manager_distribute_fds(m, fds);
- if (q < 0)
+ if (q < 0 && r == 0)
r = q;
}
/* We might have deserialized the notify fd, but if we didn't
* then let's create the bus now */
- manager_setup_notify(m);
+ q = manager_setup_notify(m);
+ if (q < 0 && r == 0)
+ r = q;
/* We might have deserialized the kdbus control fd, but if we
* didn't, then let's create the bus now. */
/* Third, fire things up! */
q = manager_coldplug(m);
- if (q < 0)
+ if (q < 0 && r == 0)
r = q;
if (serialization) {
if (u->id != t)
continue;
- if (!unit_can_serialize(u))
- continue;
-
/* Start marker */
fputs(u->id, f);
fputc('\n', f);
q = lookup_paths_init(
&m->lookup_paths, m->running_as, true,
+ NULL,
m->generator_unit_path,
m->generator_unit_path_early,
m->generator_unit_path_late);
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;
+ Unit *u = NULL;
+ Iterator i;
assert(m);
/* Turn off confirm spawn now */
m->confirm_spawn = false;
+ /* This is no longer the first boot */
+ manager_set_first_boot(m, false);
+
if (dual_timestamp_is_set(&m->finish_timestamp))
return;
NULL);
}
+ SET_FOREACH(u, m->startup_units, i)
+ if (u->cgroup_path)
+ cgroup_context_apply(unit_get_cgroup_context(u), unit_get_cgroup_mask(u), u->cgroup_path, manager_state(m));
+
bus_manager_send_finished(m, firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec);
sd_notifyf(false,
assert(m);
+ if (m->test_run)
+ return;
+
generator_path = m->running_as == SYSTEMD_SYSTEM ? SYSTEM_GENERATOR_PATH : USER_GENERATOR_PATH;
d = opendir(generator_path);
if (!d) {
return plymouth_running();
}
+void manager_set_first_boot(Manager *m, bool b) {
+ assert(m);
+
+ if (m->running_as != SYSTEMD_SYSTEM)
+ return;
+
+ m->first_boot = b;
+
+ if (m->first_boot)
+ touch("/run/systemd/first-boot");
+ else
+ unlink("/run/systemd/first-boot");
+}
+
void manager_status_printf(Manager *m, bool ephemeral, const char *status, const char *format, ...) {
va_list ap;