diff --git a/src/analyze/analyze-verify.c b/src/analyze/analyze-verify.c index ed369532d4..402203a3c7 100644 --- a/src/analyze/analyze-verify.c +++ b/src/analyze/analyze-verify.c @@ -225,9 +225,10 @@ static int verify_unit(Unit *u, bool check_man) { } int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run_generators) { - const uint8_t flags = MANAGER_TEST_RUN_BASIC | - MANAGER_TEST_RUN_ENV_GENERATORS | - run_generators * MANAGER_TEST_RUN_GENERATORS; + const ManagerTestRunFlags flags = + MANAGER_TEST_RUN_BASIC | + MANAGER_TEST_RUN_ENV_GENERATORS | + run_generators * MANAGER_TEST_RUN_GENERATORS; _cleanup_(manager_freep) Manager *m = NULL; Unit *units[strv_length(filenames)]; @@ -253,7 +254,7 @@ int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run r = manager_startup(m, NULL, NULL); if (r < 0) - return log_error_errno(r, "Failed to start manager: %m"); + return r; manager_clear_jobs(m); diff --git a/src/core/automount.c b/src/core/automount.c index 21b3887e67..70232f358d 100644 --- a/src/core/automount.c +++ b/src/core/automount.c @@ -85,7 +85,7 @@ static void unmount_autofs(Automount *a) { a->pipe_fd = safe_close(a->pipe_fd); /* If we reload/reexecute things we keep the mount point around */ - if (!IN_SET(UNIT(a)->manager->exit_code, MANAGER_RELOAD, MANAGER_REEXECUTE)) { + if (!IN_SET(UNIT(a)->manager->objective, MANAGER_RELOAD, MANAGER_REEXECUTE)) { automount_send_ready(a, a->tokens, -EHOSTDOWN); automount_send_ready(a, a->expire_tokens, -EHOSTDOWN); diff --git a/src/core/cgroup.c b/src/core/cgroup.c index a34df2538f..9f5e67ba22 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -2362,7 +2362,7 @@ int manager_setup_cgroup(Manager *m) { (void) sd_event_source_set_description(m->cgroup_inotify_event_source, "cgroup-inotify"); - } else if (MANAGER_IS_SYSTEM(m) && m->test_run_flags == 0) { + } else if (MANAGER_IS_SYSTEM(m) && !MANAGER_IS_TEST_RUN(m)) { /* On the legacy hierarchy we only get notifications via cgroup agents. (Which isn't really reliable, * since it does not generate events when control groups with children run empty. */ @@ -2391,11 +2391,11 @@ int manager_setup_cgroup(Manager *m) { if (m->pin_cgroupfs_fd < 0) return log_error_errno(errno, "Failed to open pin file: %m"); - } else if (!m->test_run_flags) + } else if (!MANAGER_IS_TEST_RUN(m)) return log_error_errno(r, "Failed to create %s control group: %m", scope_path); /* 7. Always enable hierarchical support if it exists... */ - if (!all_unified && m->test_run_flags == 0) + if (!all_unified && !MANAGER_IS_TEST_RUN(m)) (void) cg_set_attribute("memory", "/", "memory.use_hierarchy", "1"); /* 8. Figure out which controllers are supported */ diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 1d5237614e..480a143091 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -1334,7 +1334,7 @@ static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error * if (r < 0) return r; - m->exit_code = MANAGER_RELOAD; + m->objective = MANAGER_RELOAD; return 1; } @@ -1363,7 +1363,7 @@ static int method_reexecute(sd_bus_message *message, void *userdata, sd_bus_erro /* We don't send a reply back here, the client should * just wait for us disconnecting. */ - m->exit_code = MANAGER_REEXECUTE; + m->objective = MANAGER_REEXECUTE; return 1; } @@ -1383,7 +1383,7 @@ static int method_exit(sd_bus_message *message, void *userdata, sd_bus_error *er * systemd-shutdown if it cannot do the exit() because it isn't a * container. */ - m->exit_code = MANAGER_EXIT; + m->objective = MANAGER_EXIT; return sd_bus_reply_method_return(message, NULL); } @@ -1402,7 +1402,7 @@ static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error * if (!MANAGER_IS_SYSTEM(m)) return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers."); - m->exit_code = MANAGER_REBOOT; + m->objective = MANAGER_REBOOT; return sd_bus_reply_method_return(message, NULL); } @@ -1421,7 +1421,7 @@ static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error if (!MANAGER_IS_SYSTEM(m)) return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers."); - m->exit_code = MANAGER_POWEROFF; + m->objective = MANAGER_POWEROFF; return sd_bus_reply_method_return(message, NULL); } @@ -1440,7 +1440,7 @@ static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *er if (!MANAGER_IS_SYSTEM(m)) return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Halt is only supported for system managers."); - m->exit_code = MANAGER_HALT; + m->objective = MANAGER_HALT; return sd_bus_reply_method_return(message, NULL); } @@ -1459,7 +1459,7 @@ static int method_kexec(sd_bus_message *message, void *userdata, sd_bus_error *e if (!MANAGER_IS_SYSTEM(m)) return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "KExec is only supported for system managers."); - m->exit_code = MANAGER_KEXEC; + m->objective = MANAGER_KEXEC; return sd_bus_reply_method_return(message, NULL); } @@ -1549,7 +1549,7 @@ static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_er free(m->switch_root_init); m->switch_root_init = ri; - m->exit_code = MANAGER_SWITCH_ROOT; + m->objective = MANAGER_SWITCH_ROOT; return sd_bus_reply_method_return(message, NULL); } diff --git a/src/core/emergency-action.c b/src/core/emergency-action.c index 5420db8a87..6f0b0a8f33 100644 --- a/src/core/emergency-action.c +++ b/src/core/emergency-action.c @@ -41,7 +41,7 @@ int emergency_action( * in user mode */ log_warning("Exiting: %s", reason); - m->exit_code = MANAGER_EXIT; + m->objective = MANAGER_EXIT; return -ECANCELED; } @@ -59,7 +59,7 @@ int emergency_action( log_and_status(m, "Forcibly rebooting", reason); (void) update_reboot_parameter_and_warn(reboot_arg); - m->exit_code = MANAGER_REBOOT; + m->objective = MANAGER_REBOOT; break; @@ -85,7 +85,7 @@ int emergency_action( case EMERGENCY_ACTION_POWEROFF_FORCE: log_and_status(m, "Forcibly powering off", reason); - m->exit_code = MANAGER_POWEROFF; + m->objective = MANAGER_POWEROFF; break; case EMERGENCY_ACTION_POWEROFF_IMMEDIATE: diff --git a/src/core/main.c b/src/core/main.c index 88656dcabf..01f88827fe 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1115,14 +1115,19 @@ static int help(void) { return 0; } -static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool switching_root) { +static int prepare_reexecute( + Manager *m, + FILE **ret_f, + FDSet **ret_fds, + bool switching_root) { + _cleanup_fdset_free_ FDSet *fds = NULL; _cleanup_fclose_ FILE *f = NULL; int r; assert(m); - assert(_f); - assert(_fds); + assert(ret_f); + assert(ret_fds); r = manager_open_serialization(m, &f); if (r < 0) @@ -1151,8 +1156,8 @@ static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool switching if (r < 0) return log_error_errno(r, "Failed to disable O_CLOEXEC for serialization fds: %m"); - *_f = TAKE_PTR(f); - *_fds = TAKE_PTR(fds); + *ret_f = TAKE_PTR(f); + *ret_fds = TAKE_PTR(fds); return 0; } @@ -1668,7 +1673,7 @@ static int invoke_main_loop( return log_emergency_errno(r, "Failed to run main loop: %m"); } - switch (m->exit_code) { + switch ((ManagerObjective) r) { case MANAGER_RELOAD: { LogTarget saved_log_target; @@ -1695,7 +1700,8 @@ static int invoke_main_loop( r = manager_reload(m); if (r < 0) - log_warning_errno(r, "Failed to reload, ignoring: %m"); + /* Reloading failed before the point of no return. Let's continue running as if nothing happened. */ + m->objective = MANAGER_OK; break; } @@ -1759,19 +1765,19 @@ static int invoke_main_loop( case MANAGER_POWEROFF: case MANAGER_HALT: case MANAGER_KEXEC: { - static const char * const table[_MANAGER_EXIT_CODE_MAX] = { - [MANAGER_EXIT] = "exit", - [MANAGER_REBOOT] = "reboot", + static const char * const table[_MANAGER_OBJECTIVE_MAX] = { + [MANAGER_EXIT] = "exit", + [MANAGER_REBOOT] = "reboot", [MANAGER_POWEROFF] = "poweroff", - [MANAGER_HALT] = "halt", - [MANAGER_KEXEC] = "kexec" + [MANAGER_HALT] = "halt", + [MANAGER_KEXEC] = "kexec", }; log_notice("Shutting down."); *ret_reexecute = false; *ret_retval = m->return_value; - assert_se(*ret_shutdown_verb = table[m->exit_code]); + assert_se(*ret_shutdown_verb = table[m->objective]); *ret_fds = NULL; *ret_switch_root_dir = *ret_switch_root_init = NULL; @@ -1779,7 +1785,7 @@ static int invoke_main_loop( } default: - assert_not_reached("Unknown exit code."); + assert_not_reached("Unknown or unexpected manager objective."); } } } @@ -2425,7 +2431,6 @@ int main(int argc, char *argv[]) { r = manager_startup(m, arg_serialization, fds); if (r < 0) { - log_error_errno(r, "Failed to fully start up daemon: %m"); error_message = "Failed to start up manager"; goto finish; } diff --git a/src/core/manager.c b/src/core/manager.c index c361a1ec07..2dea89dc01 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -351,7 +351,7 @@ static int manager_setup_time_change(Manager *m) { assert(m); - if (m->test_run_flags) + if (MANAGER_IS_TEST_RUN(m)) return 0; m->time_change_event_source = sd_event_source_unref(m->time_change_event_source); @@ -407,7 +407,7 @@ static int manager_setup_timezone_change(Manager *m) { assert(m); - if (m->test_run_flags != 0) + if (MANAGER_IS_TEST_RUN(m)) return 0; /* We watch /etc/localtime for three events: change of the link count (which might mean removal from /etc even @@ -446,7 +446,7 @@ static int enable_special_signals(Manager *m) { assert(m); - if (m->test_run_flags) + if (MANAGER_IS_TEST_RUN(m)) return 0; /* Enable that we get SIGINT on control-alt-del. In containers @@ -711,28 +711,51 @@ static int manager_setup_sigchld_event_source(Manager *m) { return 0; } -int manager_new(UnitFileScope scope, unsigned test_run_flags, Manager **_m) { +int manager_new(UnitFileScope scope, ManagerTestRunFlags test_run_flags, Manager **_m) { _cleanup_(manager_freep) Manager *m = NULL; int r; assert(_m); assert(IN_SET(scope, UNIT_FILE_SYSTEM, UNIT_FILE_USER)); - m = new0(Manager, 1); + m = new(Manager, 1); if (!m) return -ENOMEM; - m->unit_file_scope = scope; - m->exit_code = _MANAGER_EXIT_CODE_INVALID; - m->default_timer_accuracy_usec = USEC_PER_MINUTE; - m->default_memory_accounting = MEMORY_ACCOUNTING_DEFAULT; - m->default_tasks_accounting = true; - m->default_tasks_max = UINT64_MAX; - m->default_timeout_start_usec = DEFAULT_TIMEOUT_USEC; - m->default_timeout_stop_usec = DEFAULT_TIMEOUT_USEC; - m->default_restart_usec = DEFAULT_RESTART_USEC; - m->original_log_level = -1; - m->original_log_target = _LOG_TARGET_INVALID; + *m = (Manager) { + .unit_file_scope = scope, + .objective = _MANAGER_OBJECTIVE_INVALID, + + .default_timer_accuracy_usec = USEC_PER_MINUTE, + .default_memory_accounting = MEMORY_ACCOUNTING_DEFAULT, + .default_tasks_accounting = true, + .default_tasks_max = UINT64_MAX, + .default_timeout_start_usec = DEFAULT_TIMEOUT_USEC, + .default_timeout_stop_usec = DEFAULT_TIMEOUT_USEC, + .default_restart_usec = DEFAULT_RESTART_USEC, + + .original_log_level = -1, + .original_log_target = _LOG_TARGET_INVALID, + + .notify_fd = -1, + .cgroups_agent_fd = -1, + .signal_fd = -1, + .time_change_fd = -1, + .user_lookup_fds = { -1, -1 }, + .private_listen_fd = -1, + .dev_autofs_fd = -1, + .cgroup_inotify_fd = -1, + .pin_cgroupfs_fd = -1, + .ask_password_inotify_fd = -1, + .idle_pipe = { -1, -1, -1, -1}, + + /* start as id #1, so that we can leave #0 around as "null-like" value */ + .current_job_id = 1, + + .have_ask_password = -EINVAL, /* we don't know */ + .first_boot = -1, + .test_run_flags = test_run_flags, + }; #if ENABLE_EFI if (MANAGER_IS_SYSTEM(m) && detect_container() <= 0) @@ -756,21 +779,6 @@ int manager_new(UnitFileScope scope, unsigned test_run_flags, Manager **_m) { m->invocation_log_format_string = "USER_INVOCATION_ID=%s"; } - 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->cgroups_agent_fd = m->signal_fd = m->time_change_fd = - m->dev_autofs_fd = m->private_listen_fd = m->cgroup_inotify_fd = - m->ask_password_inotify_fd = -1; - - m->user_lookup_fds[0] = m->user_lookup_fds[1] = -1; - - m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */ - - m->have_ask_password = -EINVAL; /* we don't know */ - m->first_boot = -1; - - m->test_run_flags = test_run_flags; - /* Reboot immediately if the user hits C-A-D more often than 7x per 2s */ RATELIMIT_INIT(m->ctrl_alt_del_ratelimit, 2 * USEC_PER_SEC, 7); @@ -857,7 +865,7 @@ int manager_new(UnitFileScope scope, unsigned test_run_flags, Manager **_m) { static int manager_setup_notify(Manager *m) { int r; - if (m->test_run_flags) + if (MANAGER_IS_TEST_RUN(m)) return 0; if (m->notify_fd < 0) { @@ -936,7 +944,7 @@ static int manager_setup_cgroups_agent(Manager *m) { * to it. The system instance hence listens on this special socket, but the user instances listen on the system * bus for these messages. */ - if (m->test_run_flags) + if (MANAGER_IS_TEST_RUN(m)) return 0; if (!MANAGER_IS_SYSTEM(m)) @@ -1275,8 +1283,8 @@ static void manager_clear_jobs_and_units(Manager *m) { } Manager* manager_free(Manager *m) { - UnitType c; ExecDirectoryType dt; + UnitType c; if (!m) return NULL; @@ -1287,8 +1295,8 @@ Manager* manager_free(Manager *m) { if (unit_vtable[c]->shutdown) unit_vtable[c]->shutdown(m); - /* If we reexecute ourselves, we keep the root cgroup around */ - manager_shutdown_cgroup(m, m->exit_code != MANAGER_REEXECUTE); + /* Keep the cgroup hierarchy in place except when we know we are going down for good */ + manager_shutdown_cgroup(m, IN_SET(m->objective, MANAGER_EXIT, MANAGER_REBOOT, MANAGER_POWEROFF, MANAGER_HALT, MANAGER_KEXEC)); lookup_paths_flush_generator(&m->lookup_paths); @@ -1513,7 +1521,7 @@ static bool manager_dbus_is_running(Manager *m, bool deserialized) { * and the service unit. If the 'deserialized' parameter is true we'll check the deserialized state of the unit * rather than the current one. */ - if (m->test_run_flags != 0) + if (MANAGER_IS_TEST_RUN(m)) return false; u = manager_get_unit(m, SPECIAL_DBUS_SOCKET); @@ -1561,7 +1569,7 @@ static void manager_preset_all(Manager *m) { if (!MANAGER_IS_SYSTEM(m)) return; - if (m->test_run_flags != 0) + if (MANAGER_IS_TEST_RUN(m)) return; /* If this is the first boot, and we are in the host system, then preset everything */ @@ -1573,6 +1581,38 @@ static void manager_preset_all(Manager *m) { log_info("Populated /etc with preset unit settings."); } +static void manager_vacuum(Manager *m) { + assert(m); + + /* Release any dynamic users no longer referenced */ + dynamic_user_vacuum(m, true); + + /* Release any references to UIDs/GIDs no longer referenced, and destroy any IPC owned by them */ + manager_vacuum_uid_refs(m); + manager_vacuum_gid_refs(m); + + /* Release any runtimes no longer referenced */ + exec_runtime_vacuum(m); +} + +static void manager_ready(Manager *m) { + assert(m); + + /* After having loaded everything, do the final round of catching up with what might have changed */ + + m->objective = MANAGER_OK; /* Tell everyone we are up now */ + + /* It might be safe to log to the journal now and connect to dbus */ + manager_recheck_journal(m); + manager_recheck_dbus(m); + + /* Sync current state of bus names with our set of listening units */ + (void) manager_enqueue_sync_bus_names(m); + + /* Let's finally catch up with any changes that took place while we were reloading/reexecing */ + manager_catchup(m); +} + int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { int r; @@ -1581,28 +1621,29 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { /* If we are running in test mode, we still want to run the generators, * but we should not touch the real generator directories. */ r = lookup_paths_init(&m->lookup_paths, m->unit_file_scope, - m->test_run_flags ? LOOKUP_PATHS_TEMPORARY_GENERATED : 0, + MANAGER_IS_TEST_RUN(m) ? LOOKUP_PATHS_TEMPORARY_GENERATED : 0, NULL); if (r < 0) - return r; - - r = manager_run_environment_generators(m); - if (r < 0) - return r; + return log_error_errno(r, "Failed to initialize path lookup table: %m"); dual_timestamp_get(m->timestamps + manager_timestamp_initrd_mangle(MANAGER_TIMESTAMP_GENERATORS_START)); - r = manager_run_generators(m); + r = manager_run_environment_generators(m); + if (r >= 0) + r = manager_run_generators(m); dual_timestamp_get(m->timestamps + manager_timestamp_initrd_mangle(MANAGER_TIMESTAMP_GENERATORS_FINISH)); if (r < 0) return r; manager_preset_all(m); - lookup_paths_reduce(&m->lookup_paths); + + r = lookup_paths_reduce(&m->lookup_paths); + if (r < 0) + log_warning_errno(r, "Failed ot reduce unit file paths, ignoring: %m"); + manager_build_unit_path_cache(m); - /* If we will deserialize make sure that during enumeration - * this is already known, so we increase the counter here - * already */ + /* If we will deserialize make sure that during enumeration this is already known, so we increase the counter + * here already */ if (serialization) m->n_reloading++; @@ -1619,14 +1660,11 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { return log_error_errno(r, "Deserialization failed: %m"); } - /* Any fds left? Find some unit which wants them. This is - * useful to allow container managers to pass some file - * descriptors to us pre-initialized. This enables - * socket-based activation of entire containers. */ + /* Any fds left? Find some unit which wants them. This is useful to allow container managers to pass some file + * descriptors to us pre-initialized. This enables socket-based activation of entire containers. */ manager_distribute_fds(m, fds); - /* We might have deserialized the notify fd, but if we didn't - * then let's create the bus now */ + /* We might have deserialized the notify fd, but if we didn't then let's create the bus now */ r = manager_setup_notify(m); if (r < 0) /* No sense to continue without notifications, our children would fail anyway. */ @@ -1646,33 +1684,27 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { manager_setup_bus(m); /* Now that we are connected to all possible busses, let's deserialize who is tracking us. */ - (void) bus_track_coldplug(m, &m->subscribed, false, m->deserialized_subscribed); + r = bus_track_coldplug(m, &m->subscribed, false, m->deserialized_subscribed); + if (r < 0) + log_warning_errno(r, "Failed to deserialized tracked clients, ignoring: %m"); m->deserialized_subscribed = strv_free(m->deserialized_subscribed); /* Third, fire things up! */ manager_coldplug(m); - /* Release any dynamic users no longer referenced */ - dynamic_user_vacuum(m, true); - - exec_runtime_vacuum(m); - - /* Release any references to UIDs/GIDs no longer referenced, and destroy any IPC owned by them */ - manager_vacuum_uid_refs(m); - manager_vacuum_gid_refs(m); + /* Clean up runtime objects */ + manager_vacuum(m); if (serialization) { assert(m->n_reloading > 0); m->n_reloading--; - /* Let's wait for the UnitNew/JobNew messages being - * sent, before we notify that the reload is + /* Let's wait for the UnitNew/JobNew messages being sent, before we notify that the reload is * finished */ m->send_reloading_done = true; } - /* Let's finally catch up with any changes that took place while we were reloading/reexecing */ - manager_catchup(m); + manager_ready(m); return 0; } @@ -2543,9 +2575,10 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t case SIGTERM: if (MANAGER_IS_SYSTEM(m)) { /* 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; + if (verify_run_space_and_log("Refusing to reexecute") < 0) + break; + + m->objective = MANAGER_REEXECUTE; break; } @@ -2601,9 +2634,10 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t } case SIGHUP: - r = verify_run_space_and_log("Refusing to reload"); - if (r >= 0) - m->exit_code = MANAGER_RELOAD; + if (verify_run_space_and_log("Refusing to reload") < 0) + break; + + m->objective = MANAGER_RELOAD; break; default: { @@ -2623,7 +2657,7 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t }; /* Starting SIGRTMIN+13, so that target halt and system halt are 10 apart */ - static const ManagerExitCode code_table[] = { + static const ManagerObjective objective_table[] = { [0] = MANAGER_HALT, [1] = MANAGER_POWEROFF, [2] = MANAGER_REBOOT, @@ -2639,8 +2673,8 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t } 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]; + (int) sfsi.ssi_signo < SIGRTMIN+13+(int) ELEMENTSOF(objective_table)) { + m->objective = objective_table[sfsi.ssi_signo - SIGRTMIN - 13]; break; } @@ -2664,7 +2698,7 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t case 24: if (MANAGER_IS_USER(m)) { - m->exit_code = MANAGER_EXIT; + m->objective = MANAGER_EXIT; return 0; } @@ -2793,7 +2827,7 @@ int manager_loop(Manager *m) { RATELIMIT_DEFINE(rl, 1*USEC_PER_SEC, 50000); assert(m); - m->exit_code = MANAGER_OK; + assert(m->objective == MANAGER_OK); /* Ensure manager_startup() has been called */ /* Release the path cache */ m->unit_path_cache = set_free_free(m->unit_path_cache); @@ -2805,7 +2839,7 @@ int manager_loop(Manager *m) { if (r < 0) return log_error_errno(r, "Failed to enable SIGCHLD event source: %m"); - while (m->exit_code == MANAGER_OK) { + while (m->objective == MANAGER_OK) { usec_t wait_usec; if (m->runtime_watchdog > 0 && m->runtime_watchdog != USEC_INFINITY && MANAGER_IS_SYSTEM(m)) @@ -2851,7 +2885,7 @@ int manager_loop(Manager *m) { return log_error_errno(r, "Failed to run event loop: %m"); } - return m->exit_code; + return m->objective; } int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e, Unit **_u) { @@ -3033,7 +3067,12 @@ int manager_open_serialization(Manager *m, FILE **_f) { return 0; } -int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { +int manager_serialize( + Manager *m, + FILE *f, + FDSet *fds, + bool switching_root) { + ManagerTimestamp q; const char *t; Iterator i; @@ -3087,8 +3126,10 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { int copy; copy = fdset_put_dup(fds, m->notify_fd); - if (copy < 0) - return copy; + if (copy < 0) { + r = copy; + goto finish; + } fprintf(f, "notify-fd=%i\n", copy); fprintf(f, "notify-socket=%s\n", m->notify_socket); @@ -3098,8 +3139,10 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { int copy; copy = fdset_put_dup(fds, m->cgroups_agent_fd); - if (copy < 0) - return copy; + if (copy < 0) { + r = copy; + goto finish; + } fprintf(f, "cgroups-agent-fd=%i\n", copy); } @@ -3108,12 +3151,16 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { int copy0, copy1; copy0 = fdset_put_dup(fds, m->user_lookup_fds[0]); - if (copy0 < 0) - return copy0; + if (copy0 < 0) { + r = copy0; + goto finish; + } copy1 = fdset_put_dup(fds, m->user_lookup_fds[1]); - if (copy1 < 0) - return copy1; + if (copy1 < 0) { + r = copy1; + goto finish; + } fprintf(f, "user-lookup=%i %i\n", copy0, copy1); } @@ -3122,14 +3169,14 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { r = dynamic_user_serialize(m, f, fds); if (r < 0) - return r; + goto finish; manager_serialize_uid_refs(m, f); manager_serialize_gid_refs(m, f); r = exec_runtime_serialize(m, f, fds); if (r < 0) - return r; + goto finish; (void) fputc('\n', f); @@ -3142,24 +3189,25 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { fputc('\n', f); r = unit_serialize(u, f, fds, !switching_root); - if (r < 0) { - m->n_reloading--; - return r; - } + if (r < 0) + goto finish; } - assert(m->n_reloading > 0); - m->n_reloading--; - r = fflush_and_check(f); if (r < 0) - return r; + goto finish; r = bus_fdset_add_all(m, fds); if (r < 0) - return r; + goto finish; - return 0; + r = 0; + +finish: + assert(m->n_reloading > 0); + m->n_reloading--; + + return r; } int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { @@ -3170,6 +3218,9 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { log_debug("Deserializing state..."); + /* If we are not in reload mode yet, enter it now. Not that this is recursive, a caller might already have + * increased it to non-zero, which is why we just increase it by one here and down again at the end of this + * call. */ m->n_reloading++; for (;;) { @@ -3195,7 +3246,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { uint32_t id; if (safe_atou32(val, &id) < 0) - log_notice("Failed to parse current job id value %s", val); + log_notice("Failed to parse current job id value '%s', ignoring.", val); else m->current_job_id = MAX(m->current_job_id, id); @@ -3203,7 +3254,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { uint32_t n; if (safe_atou32(val, &n) < 0) - log_notice("Failed to parse installed jobs counter %s", val); + log_notice("Failed to parse installed jobs counter '%s', ignoring.", val); else m->n_installed_jobs += n; @@ -3211,7 +3262,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { uint32_t n; if (safe_atou32(val, &n) < 0) - log_notice("Failed to parse failed jobs counter %s", val); + log_notice("Failed to parse failed jobs counter '%s', ignoring.", val); else m->n_failed_jobs += n; @@ -3220,7 +3271,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { b = parse_boolean(val); if (b < 0) - log_notice("Failed to parse taint /usr flag %s", val); + log_notice("Failed to parse taint /usr flag '%s', ignoring.", val); else m->taint_usr = m->taint_usr || b; @@ -3229,7 +3280,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { b = parse_boolean(val); if (b < 0) - log_notice("Failed to parse ready-sent flag %s", val); + log_notice("Failed to parse ready-sent flag '%s', ignoring.", val); else m->ready_sent = m->ready_sent || b; @@ -3238,7 +3289,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { b = parse_boolean(val); if (b < 0) - log_notice("Failed to parse taint-logged flag %s", val); + log_notice("Failed to parse taint-logged flag '%s', ignoring.", val); else m->taint_logged = m->taint_logged || b; @@ -3247,7 +3298,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { b = parse_boolean(val); if (b < 0) - log_notice("Failed to parse service-watchdogs flag %s", val); + log_notice("Failed to parse service-watchdogs flag '%s', ignoring.", val); else m->service_watchdogs = b; @@ -3256,7 +3307,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { s = show_status_from_string(val); if (s < 0) - log_notice("Failed to parse show-status flag %s", val); + log_notice("Failed to parse show-status flag '%s', ignoring.", val); else manager_set_show_status(m, s); @@ -3283,13 +3334,13 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { if (r == -ENOMEM) goto finish; if (r < 0) - log_notice_errno(r, "Failed to parse environment entry: \"%s\": %m", l); + log_notice_errno(r, "Failed to parse environment entry: \"%s\", ignoring: %m", l); } else if ((val = startswith(l, "notify-fd="))) { int fd; if (safe_atoi(val, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) - log_notice("Failed to parse notify fd: \"%s\"", val); + log_notice("Failed to parse notify fd, ignoring: \"%s\"", val); else { m->notify_event_source = sd_event_source_unref(m->notify_event_source); safe_close(m->notify_fd); @@ -3312,7 +3363,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { int fd; if (safe_atoi(val, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) - log_notice("Failed to parse cgroups agent fd: %s", val); + log_notice("Failed to parse cgroups agent fd, ignoring.: %s", val); else { m->cgroups_agent_event_source = sd_event_source_unref(m->cgroups_agent_event_source); safe_close(m->cgroups_agent_fd); @@ -3323,7 +3374,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { int fd0, fd1; if (sscanf(val, "%i %i", &fd0, &fd1) != 2 || fd0 < 0 || fd1 < 0 || fd0 == fd1 || !fdset_contains(fds, fd0) || !fdset_contains(fds, fd1)) - log_notice("Failed to parse user lookup fd: %s", val); + log_notice("Failed to parse user lookup fd, ignoring: %s", val); else { m->user_lookup_event_source = sd_event_source_unref(m->user_lookup_event_source); safe_close_pair(m->user_lookup_fds); @@ -3341,8 +3392,11 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { exec_runtime_deserialize_one(m, val, fds); else if ((val = startswith(l, "subscribed="))) { - if (strv_extend(&m->deserialized_subscribed, val) < 0) - log_oom(); + if (strv_extend(&m->deserialized_subscribed, val) < 0) { + r = -ENOMEM; + goto finish; + } + } else { ManagerTimestamp q; @@ -3359,7 +3413,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { if (q < _MANAGER_TIMESTAMP_MAX) /* found it */ dual_timestamp_deserialize(val, m->timestamps + q); else if (!startswith(l, "kdbus-fd=")) /* ignore kdbus */ - log_notice("Unknown serialization item '%s'", l); + log_notice("Unknown serialization item '%s', ignoring.", l); } } @@ -3383,18 +3437,20 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { r = manager_load_unit(m, unit_name, NULL, NULL, &u); if (r < 0) { - log_notice_errno(r, "Failed to load unit \"%s\", skipping deserialization: %m", unit_name); if (r == -ENOMEM) goto finish; + + log_notice_errno(r, "Failed to load unit \"%s\", skipping deserialization: %m", unit_name); unit_deserialize_skip(f); continue; } r = unit_deserialize(u, f, fds); if (r < 0) { - log_notice_errno(r, "Failed to deserialize unit \"%s\": %m", unit_name); if (r == -ENOMEM) goto finish; + + log_notice_errno(r, "Failed to deserialize unit \"%s\": %m", unit_name); } } @@ -3402,6 +3458,7 @@ finish: if (ferror(f)) r = -EIO; + /* We are done with reloading, decrease counter again */ assert(m->n_reloading > 0); m->n_reloading--; @@ -3420,37 +3477,42 @@ static void manager_flush_finished_jobs(Manager *m) { } int manager_reload(Manager *m) { - int r, q; - _cleanup_fclose_ FILE *f = NULL; _cleanup_fdset_free_ FDSet *fds = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; assert(m); r = manager_open_serialization(m, &f); if (r < 0) - return r; - - m->n_reloading++; - bus_manager_send_reloading(m, true); + return log_error_errno(r, "Failed to create serialization file: %m"); fds = fdset_new(); - if (!fds) { - m->n_reloading--; - return -ENOMEM; - } + if (!fds) + return log_oom(); + + /* We are officially in reload mode from here on */ + m->n_reloading++; r = manager_serialize(m, f, fds, false); if (r < 0) { - m->n_reloading--; - return r; + log_error_errno(r, "Failed to serialize manager: %m"); + goto fail; } if (fseeko(f, 0, SEEK_SET) < 0) { - m->n_reloading--; - return -errno; + r = log_error_errno(errno, "Failed to seek to beginning of serialization: %m"); + goto fail; } - /* From here on there is no way back. */ + /* 💀 This is the point of no return, from here on there is no way back. 💀 */ + + bus_manager_send_reloading(m, true); + + /* Start by flushing out all jobs and units, all generated units, all runtime environments, all dynamic users + * and everything else that is worth flushing out. We'll get it all back from the serialization — if we need + * it.*/ + manager_clear_jobs_and_units(m); lookup_paths_flush_generator(&m->lookup_paths); lookup_paths_free(&m->lookup_paths); @@ -3460,77 +3522,58 @@ int manager_reload(Manager *m) { m->gid_refs = hashmap_free(m->gid_refs); r = lookup_paths_init(&m->lookup_paths, m->unit_file_scope, 0, NULL); + if (r < 0) + log_warning_errno(r, "Failed to initialize path lookup table, ignoring: %m"); - q = manager_run_environment_generators(m); - if (q < 0 && r >= 0) - r = q; + (void) manager_run_environment_generators(m); + (void) manager_run_generators(m); - /* Find new unit paths */ - q = manager_run_generators(m); - if (q < 0 && r >= 0) - r = q; + r = lookup_paths_reduce(&m->lookup_paths); + if (r < 0) + log_warning_errno(r, "Failed ot reduce unit file paths, ignoring: %m"); - lookup_paths_reduce(&m->lookup_paths); manager_build_unit_path_cache(m); - /* First, enumerate what we can from all config files */ + /* First, enumerate what we can from kernel and suchlike */ + manager_enumerate_perpetual(m); manager_enumerate(m); /* Second, deserialize our stored data */ - q = manager_deserialize(m, f, fds); - if (q < 0) { - log_error_errno(q, "Deserialization failed: %m"); - - if (r >= 0) - r = q; - } + r = manager_deserialize(m, f, fds); + if (r < 0) + log_warning_errno(r, "Deserialization failed, proceeding anyway: %m"); + /* We don't need the serialization anymore */ f = safe_fclose(f); - /* Re-register notify_fd as event source */ - q = manager_setup_notify(m); - if (q < 0 && r >= 0) - r = q; - - q = manager_setup_cgroups_agent(m); - if (q < 0 && r >= 0) - r = q; - - q = manager_setup_user_lookup_fd(m); - if (q < 0 && r >= 0) - r = q; + /* Re-register notify_fd as event source, and set up other sockets/communication channels we might need */ + (void) manager_setup_notify(m); + (void) manager_setup_cgroups_agent(m); + (void) manager_setup_user_lookup_fd(m); /* Third, fire things up! */ manager_coldplug(m); - /* Release any dynamic users no longer referenced */ - dynamic_user_vacuum(m, true); - - /* Release any references to UIDs/GIDs no longer referenced, and destroy any IPC owned by them */ - manager_vacuum_uid_refs(m); - manager_vacuum_gid_refs(m); - - exec_runtime_vacuum(m); + /* Clean up runtime objects no longer referenced */ + manager_vacuum(m); + /* Consider the reload process complete now. */ 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); - - /* Let's finally catch up with any changes that took place while we were reloading/reexecing */ - manager_catchup(m); - - /* Sync current state of bus names with our set of listening units */ - q = manager_enqueue_sync_bus_names(m); - if (q < 0 && r >= 0) - r = q; + manager_ready(m); if (!MANAGER_IS_RELOADING(m)) manager_flush_finished_jobs(m); m->send_reloading_done = true; + return 0; + +fail: + /* Fail the call. Note that we hit this only if we fail before the point of no return, i.e. when the error is + * still something that can be handled. */ + assert(m->n_reloading > 0); + m->n_reloading--; return r; } @@ -3583,7 +3626,7 @@ static void manager_notify_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; - if (m->test_run_flags) + if (MANAGER_IS_TEST_RUN(m)) return; if (MANAGER_IS_SYSTEM(m) && detect_container() <= 0) { @@ -3778,7 +3821,7 @@ static int manager_run_environment_generators(Manager *m) { const char **paths; void* args[] = {&tmp, &tmp, &m->environment}; - if (m->test_run_flags && !(m->test_run_flags & MANAGER_TEST_RUN_ENV_GENERATORS)) + if (MANAGER_IS_TEST_RUN(m) && !(m->test_run_flags & MANAGER_TEST_RUN_ENV_GENERATORS)) return 0; paths = MANAGER_IS_SYSTEM(m) ? system_env_generator_binary_paths : user_env_generator_binary_paths; @@ -3796,7 +3839,7 @@ static int manager_run_generators(Manager *m) { assert(m); - if (m->test_run_flags && !(m->test_run_flags & MANAGER_TEST_RUN_GENERATORS)) + if (MANAGER_IS_TEST_RUN(m) && !(m->test_run_flags & MANAGER_TEST_RUN_GENERATORS)) return 0; paths = generator_binary_paths(m->unit_file_scope); @@ -3807,8 +3850,10 @@ static int manager_run_generators(Manager *m) { return 0; r = lookup_paths_mkdir_generator(&m->lookup_paths); - if (r < 0) + if (r < 0) { + log_error_errno(r, "Failed to create generator directories: %m"); goto finish; + } argv[0] = NULL; /* Leave this empty, execute_directory() will fill something in */ argv[1] = m->lookup_paths.generator; @@ -3817,8 +3862,10 @@ static int manager_run_generators(Manager *m) { argv[4] = NULL; RUN_WITH_UMASK(0022) - execute_directories((const char* const*) paths, DEFAULT_TIMEOUT_USEC, - NULL, NULL, (char**) argv, m->environment); + (void) execute_directories((const char* const*) paths, DEFAULT_TIMEOUT_USEC, + NULL, NULL, (char**) argv, m->environment); + + r = 0; finish: lookup_paths_trim_generator(&m->lookup_paths); @@ -3910,7 +3957,7 @@ static bool manager_journal_is_running(Manager *m) { assert(m); - if (m->test_run_flags != 0) + if (MANAGER_IS_TEST_RUN(m)) return false; /* If we are the user manager we can safely assume that the journal is up */ diff --git a/src/core/manager.h b/src/core/manager.h index 23e8e48a4d..6e6e251a55 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -23,6 +23,8 @@ typedef struct Unit Unit; typedef struct Manager Manager; +/* An externally visible state. We don't actually maintain this as state variable, but derive it from various fields + * when requested */ typedef enum ManagerState { MANAGER_INITIALIZING, MANAGER_STARTING, @@ -34,7 +36,7 @@ typedef enum ManagerState { _MANAGER_STATE_INVALID = -1 } ManagerState; -typedef enum ManagerExitCode { +typedef enum ManagerObjective { MANAGER_OK, MANAGER_EXIT, MANAGER_RELOAD, @@ -44,9 +46,9 @@ typedef enum ManagerExitCode { MANAGER_HALT, MANAGER_KEXEC, MANAGER_SWITCH_ROOT, - _MANAGER_EXIT_CODE_MAX, - _MANAGER_EXIT_CODE_INVALID = -1 -} ManagerExitCode; + _MANAGER_OBJECTIVE_MAX, + _MANAGER_OBJECTIVE_INVALID = -1 +} ManagerObjective; typedef enum StatusType { STATUS_TYPE_EPHEMERAL, @@ -106,14 +108,15 @@ typedef enum ManagerTimestamp { #include "show-status.h" #include "unit-name.h" -enum { - /* 0 = run normally */ - MANAGER_TEST_RUN_MINIMAL = 1 << 1, /* create basic data structures */ - MANAGER_TEST_RUN_BASIC = 1 << 2, /* interact with the environment */ - MANAGER_TEST_RUN_ENV_GENERATORS = 1 << 3, /* also run env generators */ - MANAGER_TEST_RUN_GENERATORS = 1 << 4, /* also run unit generators */ +typedef enum ManagerTestRunFlags { + MANAGER_TEST_NORMAL = 0, /* run normally */ + MANAGER_TEST_RUN_MINIMAL = 1 << 0, /* create basic data structures */ + MANAGER_TEST_RUN_BASIC = 1 << 1, /* interact with the environment */ + MANAGER_TEST_RUN_ENV_GENERATORS = 1 << 2, /* also run env generators */ + MANAGER_TEST_RUN_GENERATORS = 1 << 3, /* also run unit generators */ MANAGER_TEST_FULL = MANAGER_TEST_RUN_BASIC | MANAGER_TEST_RUN_ENV_GENERATORS | MANAGER_TEST_RUN_GENERATORS, -}; +} ManagerTestRunFlags; + assert_cc((MANAGER_TEST_FULL & UINT8_MAX) == MANAGER_TEST_FULL); struct Manager { @@ -280,9 +283,9 @@ struct Manager { usec_t etc_localtime_mtime; bool etc_localtime_accessible:1; - /* Flags */ - ManagerExitCode exit_code:5; + ManagerObjective objective:5; + /* Flags */ bool dispatching_load_queue:1; bool dispatching_dbus_queue:1; @@ -297,7 +300,7 @@ struct Manager { /* Have we ever changed the "kernel.pid_max" sysctl? */ bool sysctl_pid_max_changed:1; - unsigned test_run_flags:8; + ManagerTestRunFlags test_run_flags:8; /* If non-zero, exit with the following value when the systemd * process terminate. Useful for containers: systemd-nspawn could get @@ -405,10 +408,12 @@ struct Manager { #define MANAGER_IS_FINISHED(m) (dual_timestamp_is_set((m)->timestamps + MANAGER_TIMESTAMP_FINISH)) -/* The exit code is set to OK as soon as we enter the main loop, and set otherwise as soon as we are done with it */ -#define MANAGER_IS_RUNNING(m) ((m)->exit_code == MANAGER_OK) +/* The objective is set to OK as soon as we enter the main loop, and set otherwise as soon as we are done with it */ +#define MANAGER_IS_RUNNING(m) ((m)->objective == MANAGER_OK) -int manager_new(UnitFileScope scope, unsigned test_run_flags, Manager **m); +#define MANAGER_IS_TEST_RUN(m) ((m)->test_run_flags != 0) + +int manager_new(UnitFileScope scope, ManagerTestRunFlags test_run_flags, Manager **m); Manager* manager_free(Manager *m); DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); diff --git a/src/core/unit.c b/src/core/unit.c index 359b35b297..1b9bbf7057 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -5280,7 +5280,7 @@ void unit_export_state_files(Unit *u) { if (!MANAGER_IS_SYSTEM(u->manager)) return; - if (u->manager->test_run_flags != 0) + if (MANAGER_IS_TEST_RUN(u->manager)) return; /* Exports a couple of unit properties to /run/systemd/units/, so that journald can quickly query this data diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c index 7d7b890b47..075f4d1e6c 100644 --- a/src/shared/path-lookup.c +++ b/src/shared/path-lookup.c @@ -529,7 +529,7 @@ int lookup_paths_init( if (flags & LOOKUP_PATHS_TEMPORARY_GENERATED) { r = mkdtemp_malloc("/tmp/systemd-temporary-XXXXXX", &tempdir); if (r < 0) - return log_error_errno(r, "Failed to create temporary directory: %m"); + return log_debug_errno(r, "Failed to create temporary directory: %m"); } /* Note: when XDG_RUNTIME_DIR is not set this will not return -ENXIO, but simply set runtime_config to NULL */ diff --git a/src/test/test-bpf.c b/src/test/test-bpf.c index 2fb7968dfd..ea5f0f5bc6 100644 --- a/src/test/test-bpf.c +++ b/src/test/test-bpf.c @@ -63,7 +63,7 @@ int main(int argc, char *argv[]) { /* The simple tests suceeded. Now let's try full unit-based use-case. */ - assert_se(manager_new(UNIT_FILE_USER, true, &m) >= 0); + assert_se(manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &m) >= 0); assert_se(manager_startup(m, NULL, NULL) >= 0); assert_se(u = unit_new(m, sizeof(Service))); diff --git a/src/test/test-watch-pid.c b/src/test/test-watch-pid.c index 03378ecf08..2c6ca0a1a2 100644 --- a/src/test/test-watch-pid.c +++ b/src/test/test-watch-pid.c @@ -24,7 +24,7 @@ int main(int argc, char *argv[]) { assert_se(set_unit_path(get_testdata_dir()) >= 0); assert_se(runtime_dir = setup_fake_runtime_dir()); - assert_se(manager_new(UNIT_FILE_USER, true, &m) >= 0); + assert_se(manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &m) >= 0); assert_se(manager_startup(m, NULL, NULL) >= 0); assert_se(a = unit_new(m, sizeof(Service)));