diff options
Diffstat (limited to 'src/core/main.c')
-rw-r--r-- | src/core/main.c | 160 |
1 files changed, 82 insertions, 78 deletions
diff --git a/src/core/main.c b/src/core/main.c index 6ae8b51544..b57f4c1b7a 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -114,6 +114,7 @@ static FILE* arg_serialization = NULL; static bool arg_default_cpu_accounting = false; static bool arg_default_blockio_accounting = false; static bool arg_default_memory_accounting = false; +static bool arg_default_tasks_accounting = false; static void nop_handler(int sig) {} @@ -374,7 +375,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value) { /* Note that log_parse_environment() handles 'debug' * too, and sets the log level to LOG_DEBUG. */ - if (detect_container(NULL) > 0) + if (detect_container() > 0) log_set_target(LOG_TARGET_CONSOLE); } else if (!in_initrd() && !value) { @@ -433,25 +434,28 @@ static int config_parse_cpu_affinity2( void *data, void *userdata) { - const char *word, *state; - size_t l; - cpu_set_t *c = NULL; + const char *whole_rvalue = rvalue; + _cleanup_cpu_free_ cpu_set_t *c = NULL; unsigned ncpus = 0; assert(filename); assert(lvalue); assert(rvalue); - FOREACH_WORD_QUOTED(word, l, rvalue, state) { - char *t; - int r; + for (;;) { + _cleanup_free_ char *word = NULL; unsigned cpu; + int r; - if (!(t = strndup(word, l))) - return log_oom(); + r = extract_first_word(&rvalue, &word, WHITESPACE, EXTRACT_QUOTES); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid value for %s: %s", lvalue, whole_rvalue); + return r; + } + if (r == 0) + break; - r = safe_atou(t, &cpu); - free(t); + r = safe_atou(word, &cpu); if (!c) if (!(c = cpu_set_malloc(&ncpus))) @@ -460,23 +464,19 @@ static int config_parse_cpu_affinity2( if (r < 0 || cpu >= ncpus) { log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to parse CPU affinity '%s'", rvalue); - CPU_FREE(c); return -EBADMSG; } CPU_SET_S(cpu, CPU_ALLOC_SIZE(ncpus), c); } - if (!isempty(state)) + if (!isempty(rvalue)) log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Trailing garbage, ignoring."); - if (c) { + if (c) if (sched_setaffinity(0, CPU_ALLOC_SIZE(ncpus), c) < 0) log_warning("Failed to set CPU affinity: %m"); - CPU_FREE(c); - } - return 0; } @@ -538,9 +538,8 @@ static int config_parse_join_controllers(const char *unit, void *data, void *userdata) { + const char *whole_rvalue = rvalue; unsigned n = 0; - const char *word, *state; - size_t length; assert(filename); assert(lvalue); @@ -548,16 +547,22 @@ static int config_parse_join_controllers(const char *unit, free_join_controllers(); - FOREACH_WORD_QUOTED(word, length, rvalue, state) { - char *s, **l; - - s = strndup(word, length); - if (!s) - return log_oom(); + for (;;) { + _cleanup_free_ char *word = NULL; + char **l; + int r; - l = strv_split(s, ","); - free(s); + r = extract_first_word(&rvalue, &word, WHITESPACE, EXTRACT_QUOTES); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid value for %s: %s", lvalue, whole_rvalue); + return r; + } + if (r == 0) + break; + l = strv_split(word, ","); + if (!l) + log_oom(); strv_uniq(l); if (strv_length(l) <= 1) { @@ -617,7 +622,7 @@ static int config_parse_join_controllers(const char *unit, arg_join_controllers = t; } } - if (!isempty(state)) + if (!isempty(rvalue)) log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Trailing garbage, ignoring."); @@ -672,6 +677,7 @@ static int parse_config_file(void) { { "Manager", "DefaultCPUAccounting", config_parse_bool, 0, &arg_default_cpu_accounting }, { "Manager", "DefaultBlockIOAccounting", config_parse_bool, 0, &arg_default_blockio_accounting }, { "Manager", "DefaultMemoryAccounting", config_parse_bool, 0, &arg_default_memory_accounting }, + { "Manager", "DefaultTasksAccounting", config_parse_bool, 0, &arg_default_tasks_accounting }, {} }; @@ -700,6 +706,7 @@ static void manager_set_defaults(Manager *m) { m->default_cpu_accounting = arg_default_cpu_accounting; m->default_blockio_accounting = arg_default_blockio_accounting; m->default_memory_accounting = arg_default_memory_accounting; + m->default_tasks_accounting = arg_default_tasks_accounting; manager_set_default_rlimits(m, arg_default_rlimit); manager_environment_add(m, NULL, arg_default_environment); @@ -914,8 +921,7 @@ static int parse_argv(int argc, char *argv[]) { if (!f) return log_error_errno(errno, "Failed to open serialization fd: %m"); - if (arg_serialization) - fclose(arg_serialization); + safe_fclose(arg_serialization); arg_serialization = f; @@ -1055,8 +1061,7 @@ static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool switching fail: fdset_free(fds); - if (f) - fclose(f); + safe_fclose(f); return r; } @@ -1114,9 +1119,10 @@ static void test_mtab(void) { if (r >= 0 && nulstr_contains(ok, p)) return; - log_warning("/etc/mtab is not a symlink or not pointing to /proc/self/mounts. " - "This is not supported anymore. " - "Please make sure to replace this file by a symlink to avoid incorrect or misleading mount(8) output."); + log_error("/etc/mtab is not a symlink or not pointing to /proc/self/mounts. " + "This is not supported anymore. " + "Please make sure to replace this file by a symlink to avoid incorrect or misleading mount(8) output."); + freeze(); } static void test_usr(void) { @@ -1200,12 +1206,11 @@ static int status_welcome(void) { "PRETTY_NAME", &pretty_name, "ANSI_COLOR", &ansi_color, NULL); - if (r == -ENOENT) { + if (r == -ENOENT) r = parse_env_file("/usr/lib/os-release", NEWLINE, "PRETTY_NAME", &pretty_name, "ANSI_COLOR", &ansi_color, NULL); - } if (r < 0 && r != -ENOENT) log_warning_errno(r, "Failed to read os-release file: %m"); @@ -1249,6 +1254,7 @@ int main(int argc, char *argv[]) { char *switch_root_dir = NULL, *switch_root_init = NULL; struct rlimit saved_rlimit_nofile = RLIMIT_MAKE_CONST(0); const char *error_message = NULL; + uint8_t shutdown_exit_code = 0; #ifdef HAVE_SYSV_COMPAT if (getpid() != 1 && strstr(program_invocation_short_name, "init")) { @@ -1293,7 +1299,7 @@ int main(int argc, char *argv[]) { if (getpid() == 1) umask(0); - if (getpid() == 1 && detect_container(NULL) <= 0) { + if (getpid() == 1 && detect_container() <= 0) { /* Running outside of a container as PID 1 */ arg_running_as = MANAGER_SYSTEM; @@ -1391,8 +1397,7 @@ int main(int argc, char *argv[]) { /* clear the kernel timestamp, * because we are not PID 1 */ - kernel_timestamp.monotonic = 0ULL; - kernel_timestamp.realtime = 0ULL; + kernel_timestamp = DUAL_TIMESTAMP_NULL; } /* Initialize default unit */ @@ -1548,14 +1553,14 @@ int main(int argc, char *argv[]) { } if (arg_running_as == MANAGER_SYSTEM) { - const char *virtualization = NULL; + int v; log_info(PACKAGE_STRING " running in %ssystem mode. (" SYSTEMD_FEATURES ")", arg_action == ACTION_TEST ? "test " : "" ); - detect_virtualization(&virtualization); - if (virtualization) - log_info("Detected virtualization %s.", virtualization); + v = detect_virtualization(); + if (v > 0) + log_info("Detected virtualization %s.", virtualization_to_string(v)); write_container_id(); @@ -1676,10 +1681,7 @@ int main(int argc, char *argv[]) { fdset_free(fds); fds = NULL; - if (arg_serialization) { - fclose(arg_serialization); - arg_serialization = NULL; - } + arg_serialization = safe_fclose(arg_serialization); if (queue_default_job) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; @@ -1763,11 +1765,6 @@ int main(int argc, char *argv[]) { switch (m->exit_code) { - case MANAGER_EXIT: - retval = EXIT_SUCCESS; - log_debug("Exit."); - goto finish; - case MANAGER_RELOAD: log_info("Reloading."); @@ -1785,7 +1782,7 @@ int main(int argc, char *argv[]) { case MANAGER_REEXECUTE: if (prepare_reexecute(m, &arg_serialization, &fds, false) < 0) { - error_message = "Failed to prepare for reexection"; + error_message = "Failed to prepare for reexecution"; goto finish; } @@ -1801,7 +1798,7 @@ int main(int argc, char *argv[]) { if (!switch_root_init) if (prepare_reexecute(m, &arg_serialization, &fds, true) < 0) { - error_message = "Failed to prepare for reexection"; + error_message = "Failed to prepare for reexecution"; goto finish; } @@ -1809,11 +1806,20 @@ int main(int argc, char *argv[]) { log_notice("Switching root."); goto finish; + case MANAGER_EXIT: + if (m->running_as == MANAGER_USER) { + retval = EXIT_SUCCESS; + log_debug("Exit."); + goto finish; + } + + /* fallthrough */ case MANAGER_REBOOT: case MANAGER_POWEROFF: case MANAGER_HALT: case MANAGER_KEXEC: { static const char * const table[_MANAGER_EXIT_CODE_MAX] = { + [MANAGER_EXIT] = "exit", [MANAGER_REBOOT] = "reboot", [MANAGER_POWEROFF] = "poweroff", [MANAGER_HALT] = "halt", @@ -1835,25 +1841,22 @@ int main(int argc, char *argv[]) { finish: pager_close(); - if (m) + if (m) { arg_shutdown_watchdog = m->shutdown_watchdog; + shutdown_exit_code = m->return_value; + } m = manager_free(m); - for (j = 0; j < ELEMENTSOF(arg_default_rlimit); j++) { - free(arg_default_rlimit[j]); - arg_default_rlimit[j] = NULL; - } + for (j = 0; j < ELEMENTSOF(arg_default_rlimit); j++) + arg_default_rlimit[j] = mfree(arg_default_rlimit[j]); - free(arg_default_unit); - arg_default_unit = NULL; + arg_default_unit = mfree(arg_default_unit); free_join_controllers(); - strv_free(arg_default_environment); - arg_default_environment = NULL; + arg_default_environment = strv_free(arg_default_environment); - set_free(arg_syscall_archs); - arg_syscall_archs = NULL; + arg_syscall_archs = set_free(arg_syscall_archs); mac_selinux_finish(); @@ -1924,10 +1927,7 @@ finish: * getopt() in argv[], and some cleanups in envp[], * but let's hope that doesn't matter.) */ - if (arg_serialization) { - fclose(arg_serialization); - arg_serialization = NULL; - } + arg_serialization = safe_fclose(arg_serialization); if (fds) { fdset_free(fds); @@ -1967,10 +1967,7 @@ finish: log_warning_errno(errno, "Failed to execute /sbin/init, giving up: %m"); } - if (arg_serialization) { - fclose(arg_serialization); - arg_serialization = NULL; - } + arg_serialization = safe_fclose(arg_serialization); if (fds) { fdset_free(fds); @@ -1988,7 +1985,8 @@ finish: if (shutdown_verb) { char log_level[DECIMAL_STR_MAX(int) + 1]; - const char* command_line[9] = { + char exit_code[DECIMAL_STR_MAX(uint8_t) + 1]; + const char* command_line[11] = { SYSTEMD_SHUTDOWN_BINARY_PATH, shutdown_verb, "--log-level", log_level, @@ -2025,6 +2023,12 @@ finish: if (log_get_show_location()) command_line[pos++] = "--log-location"; + if (streq(shutdown_verb, "exit")) { + command_line[pos++] = "--exit-code"; + command_line[pos++] = exit_code; + xsprintf(exit_code, "%d", shutdown_exit_code); + } + assert(pos < ELEMENTSOF(command_line)); if (arm_reboot_watchdog && arg_shutdown_watchdog > 0) { @@ -2045,8 +2049,8 @@ finish: /* Avoid the creation of new processes forked by the * kernel; at this point, we will not listen to the * signals anyway */ - if (detect_container(NULL) <= 0) - cg_uninstall_release_agent(SYSTEMD_CGROUP_CONTROLLER); + if (detect_container() <= 0) + (void) cg_uninstall_release_agent(SYSTEMD_CGROUP_CONTROLLER); execve(SYSTEMD_SHUTDOWN_BINARY_PATH, (char **) command_line, env_block); log_error_errno(errno, "Failed to execute shutdown binary, %s: %m", @@ -2056,7 +2060,7 @@ finish: if (getpid() == 1) { if (error_message) manager_status_printf(NULL, STATUS_TYPE_EMERGENCY, - ANSI_HIGHLIGHT_RED_ON "!!!!!!" ANSI_HIGHLIGHT_OFF, + ANSI_HIGHLIGHT_RED "!!!!!!" ANSI_NORMAL, "%s, freezing.", error_message); freeze(); } |