]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/core/main.c
tree-wide: drop 'This file is part of systemd' blurb
[thirdparty/systemd.git] / src / core / main.c
index 8c04d41c0c4537883e79a1b08b21e7b4a1d33acf..b0408bc3649360700f5b8185b4dff19534aedfa6 100644 (file)
@@ -1,7 +1,5 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 /***
-  This file is part of systemd.
-
   Copyright 2010 Lennart Poettering
 ***/
 
@@ -311,6 +309,7 @@ static int parse_confirm_spawn(const char *value, char **console) {
                 s = strjoin("/dev/", value);
         if (!s)
                 return -ENOMEM;
+
         *console = s;
         return 0;
 }
@@ -524,10 +523,10 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
                 return 0;                                             \
         }
 
-DEFINE_SETTER(config_parse_level2, log_set_max_level_from_string, "log level")
-DEFINE_SETTER(config_parse_target, log_set_target_from_string, "target")
-DEFINE_SETTER(config_parse_color, log_show_color_from_string, "color" )
-DEFINE_SETTER(config_parse_location, log_show_location_from_string, "location")
+DEFINE_SETTER(config_parse_level2, log_set_max_level_from_string, "log level");
+DEFINE_SETTER(config_parse_target, log_set_target_from_string, "target");
+DEFINE_SETTER(config_parse_color, log_show_color_from_string, "color" );
+DEFINE_SETTER(config_parse_location, log_show_location_from_string, "location");
 
 static int config_parse_cpu_affinity2(
                 const char *unit,
@@ -731,6 +730,10 @@ static void set_manager_defaults(Manager *m) {
 
         assert(m);
 
+        /* Propagates the various default unit property settings into the manager object, i.e. properties that do not
+         * affect the manager itself, but are just what newly allocated units will have set if they haven't set
+         * anything else. (Also see set_manager_settings() for the settings that affect the manager's own behaviour) */
+
         m->default_timer_accuracy_usec = arg_default_timer_accuracy_usec;
         m->default_std_output = arg_default_std_output;
         m->default_std_error = arg_default_std_error;
@@ -755,6 +758,9 @@ static void set_manager_settings(Manager *m) {
 
         assert(m);
 
+        /* Propagates the various manager settings into the manager object, i.e. properties that effect the manager
+         * itself (as opposed to just being inherited into newly allocated units, see set_manager_defaults() above). */
+
         m->confirm_spawn = arg_confirm_spawn;
         m->service_watchdogs = arg_service_watchdogs;
         m->runtime_watchdog = arg_runtime_watchdog;
@@ -1136,10 +1142,7 @@ static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool switching
 }
 
 static int bump_rlimit_nofile(struct rlimit *saved_rlimit) {
-        struct rlimit nl;
-        int r;
-        int min_max;
-        _cleanup_free_ char *nr_open = NULL;
+        int r, nr;
 
         assert(saved_rlimit);
 
@@ -1160,17 +1163,9 @@ static int bump_rlimit_nofile(struct rlimit *saved_rlimit) {
                 arg_default_rlimit[RLIMIT_NOFILE] = rl;
         }
 
-        /* Get current RLIMIT_NOFILE maximum compiled into the kernel. */
-        r = read_one_line_file("/proc/sys/fs/nr_open", &nr_open);
-        if (r >= 0)
-                r = safe_atoi(nr_open, &min_max);
-        /* If we fail, fallback to the hard-coded kernel limit of 1024 * 1024. */
-        if (r < 0)
-                min_max = 1024 * 1024;
-
-        /* Bump up the resource limit for ourselves substantially */
-        nl.rlim_cur = nl.rlim_max = min_max;
-        r = setrlimit_closest(RLIMIT_NOFILE, &nl);
+        /* Bump up the resource limit for ourselves substantially, all the way to the maximum the kernel allows */
+        nr = read_nr_open();
+        r = setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(nr));
         if (r < 0)
                 return log_warning_errno(r, "Setting RLIMIT_NOFILE failed, ignoring: %m");
 
@@ -1270,10 +1265,9 @@ static int bump_unix_max_dgram_qlen(void) {
         unsigned long v;
         int r;
 
-        /* Let's bump the net.unix.max_dgram_qlen sysctl. The kernel
-         * default of 16 is simply too low. We set the value really
-         * really early during boot, so that it is actually applied to
-         * all our sockets, including the $NOTIFY_SOCKET one. */
+        /* Let's bump the net.unix.max_dgram_qlen sysctl. The kernel default of 16 is simply too low. We set the value
+         * really really early during boot, so that it is actually applied to all our sockets, including the
+         * $NOTIFY_SOCKET one. */
 
         r = read_one_line_file("/proc/sys/net/unix/max_dgram_qlen", &qlen);
         if (r < 0)
@@ -1281,16 +1275,12 @@ static int bump_unix_max_dgram_qlen(void) {
 
         r = safe_atolu(qlen, &v);
         if (r < 0)
-                return log_warning_errno(r, "Failed to parse AF_UNIX datagram queue length, ignoring: %m");
+                return log_warning_errno(r, "Failed to parse AF_UNIX datagram queue length '%s', ignoring: %m", qlen);
 
         if (v >= DEFAULT_UNIX_MAX_DGRAM_QLEN)
                 return 0;
 
-        qlen = mfree(qlen);
-        if (asprintf(&qlen, "%lu\n", DEFAULT_UNIX_MAX_DGRAM_QLEN) < 0)
-                return log_oom();
-
-        r = write_string_file("/proc/sys/net/unix/max_dgram_qlen", qlen, 0);
+        r = write_string_filef("/proc/sys/net/unix/max_dgram_qlen", 0, "%lu", DEFAULT_UNIX_MAX_DGRAM_QLEN);
         if (r < 0)
                 return log_full_errno(IN_SET(r, -EROFS, -EPERM, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
                                       "Failed to bump AF_UNIX datagram queue length, ignoring: %m");
@@ -1648,20 +1638,35 @@ static int invoke_main_loop(
 
                 switch (m->exit_code) {
 
-                case MANAGER_RELOAD:
+                case MANAGER_RELOAD: {
+                        LogTarget saved_log_target;
+                        int saved_log_level;
+
                         log_info("Reloading.");
 
+                        /* First, save any overriden log level/target, then parse the configuration file, which might
+                         * change the log level to new settings. */
+
+                        saved_log_level = m->log_level_overridden ? log_get_max_level() : -1;
+                        saved_log_target = m->log_target_overridden ? log_get_target() : _LOG_TARGET_INVALID;
+
                         r = parse_config_file();
                         if (r < 0)
                                 log_warning_errno(r, "Failed to parse config file, ignoring: %m");
 
                         set_manager_defaults(m);
 
+                        if (saved_log_level >= 0)
+                                manager_override_log_level(m, saved_log_level);
+                        if (saved_log_target >= 0)
+                                manager_override_log_target(m, saved_log_target);
+
                         r = manager_reload(m);
                         if (r < 0)
                                 log_warning_errno(r, "Failed to reload, ignoring: %m");
 
                         break;
+                }
 
                 case MANAGER_REEXECUTE:
 
@@ -1934,12 +1939,9 @@ static int do_queue_default_job(
 }
 
 static void free_arguments(void) {
-        size_t j;
 
         /* Frees all arg_* variables, with the exception of arg_serialization */
-
-        for (j = 0; j < ELEMENTSOF(arg_default_rlimit); j++)
-                arg_default_rlimit[j] = mfree(arg_default_rlimit[j]);
+        rlimit_free_all(arg_default_rlimit);
 
         arg_default_unit = mfree(arg_default_unit);
         arg_confirm_spawn = mfree(arg_confirm_spawn);
@@ -2136,7 +2138,6 @@ static bool early_skip_setup_check(int argc, char *argv[]) {
          * anyway, even if in that case we also do deserialization. */
 
         for (i = 1; i < argc; i++) {
-
                 if (streq(argv[i], "--switched-root"))
                         return false; /* If we switched root, don't skip the setup. */
                 else if (streq(argv[i], "--deserialize"))
@@ -2185,11 +2186,14 @@ int main(int argc, char *argv[]) {
         log_set_upgrade_syslog_to_journal(true);
 
         if (getpid_cached() == 1) {
+                /* When we run as PID 1 force system mode */
+                arg_system = true;
+
                 /* Disable the umask logic */
                 umask(0);
 
-                /* Make sure that at least initially we do not ever log to journald/syslogd, because it might not be activated
-                 * yet (even though the log socket for it exists). */
+                /* Make sure that at least initially we do not ever log to journald/syslogd, because it might not be
+                 * activated yet (even though the log socket for it exists). */
                 log_set_prohibit_ipc(true);
 
                 /* Always reopen /dev/console when running as PID 1 or one of its pre-execve() children. This is
@@ -2197,62 +2201,68 @@ int main(int argc, char *argv[]) {
                  * child process right before execve()'ing the actual binary, at a point in time where socket
                  * activation stderr/stdout area already set up. */
                 log_set_always_reopen_console(true);
-        }
 
-        if (getpid_cached() == 1 && detect_container() <= 0) {
+                if (detect_container() <= 0) {
 
-                /* Running outside of a container as PID 1 */
-                arg_system = true;
-                log_set_target(LOG_TARGET_KMSG);
-                log_open();
+                        /* Running outside of a container as PID 1 */
+                        log_set_target(LOG_TARGET_KMSG);
+                        log_open();
 
-                if (in_initrd())
-                        initrd_timestamp = userspace_timestamp;
+                        if (in_initrd())
+                                initrd_timestamp = userspace_timestamp;
 
-                if (!skip_setup) {
-                        r = mount_setup_early();
-                        if (r < 0) {
-                                error_message = "Failed to mount early API filesystems";
-                                goto finish;
+                        if (!skip_setup) {
+                                r = mount_setup_early();
+                                if (r < 0) {
+                                        error_message = "Failed to mount early API filesystems";
+                                        goto finish;
+                                }
+
+                                r = initialize_security(
+                                                &loaded_policy,
+                                                &security_start_timestamp,
+                                                &security_finish_timestamp,
+                                                &error_message);
+                                if (r < 0)
+                                        goto finish;
                         }
 
-                        r = initialize_security(
-                                        &loaded_policy,
-                                        &security_start_timestamp,
-                                        &security_finish_timestamp,
-                                        &error_message);
-                        if (r < 0)
+                        if (mac_selinux_init() < 0) {
+                                error_message = "Failed to initialize SELinux policy";
                                 goto finish;
-                }
+                        }
 
-                if (mac_selinux_init() < 0) {
-                        error_message = "Failed to initialize SELinux policy";
-                        goto finish;
+                        if (!skip_setup)
+                                initialize_clock();
+
+                        /* Set the default for later on, but don't actually open the logs like this for now. Note that
+                         * if we are transitioning from the initrd there might still be journal fd open, and we
+                         * shouldn't attempt opening that before we parsed /proc/cmdline which might redirect output
+                         * elsewhere. */
+                        log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
+
+                } else {
+                        /* Running inside a container, as PID 1 */
+                        log_set_target(LOG_TARGET_CONSOLE);
+                        log_open();
+
+                        /* For later on, see above... */
+                        log_set_target(LOG_TARGET_JOURNAL);
+
+                        /* clear the kernel timestamp,
+                         * because we are in a container */
+                        kernel_timestamp = DUAL_TIMESTAMP_NULL;
                 }
 
-                if (!skip_setup)
-                        initialize_clock();
-
-                /* Set the default for later on, but don't actually
-                 * open the logs like this for now. Note that if we
-                 * are transitioning from the initrd there might still
-                 * be journal fd open, and we shouldn't attempt
-                 * opening that before we parsed /proc/cmdline which
-                 * might redirect output elsewhere. */
-                log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
-
-        } else if (getpid_cached() == 1) {
-                /* Running inside a container, as PID 1 */
-                arg_system = true;
-                log_set_target(LOG_TARGET_CONSOLE);
-                log_open();
+                initialize_coredump(skip_setup);
 
-                /* For later on, see above... */
-                log_set_target(LOG_TARGET_JOURNAL);
+                r = fixup_environment();
+                if (r < 0) {
+                        log_emergency_errno(r, "Failed to fix up PID 1 environment: %m");
+                        error_message = "Failed to fix up PID1 environment";
+                        goto finish;
+                }
 
-                /* clear the kernel timestamp,
-                 * because we are in a container */
-                kernel_timestamp = DUAL_TIMESTAMP_NULL;
         } else {
                 /* Running as user instance */
                 arg_system = false;
@@ -2264,24 +2274,14 @@ int main(int argc, char *argv[]) {
                 kernel_timestamp = DUAL_TIMESTAMP_NULL;
         }
 
-        initialize_coredump(skip_setup);
-
-        r = fixup_environment();
-        if (r < 0) {
-                log_emergency_errno(r, "Failed to fix up PID 1 environment: %m");
-                error_message = "Failed to fix up PID1 environment";
-                goto finish;
-        }
-
         if (arg_system) {
-
-                /* Try to figure out if we can use colors with the console. No
-                 * need to do that for user instances since they never log
-                 * into the console. */
+                /* Try to figure out if we can use colors with the console. No need to do that for user instances since
+                 * they never log into the console. */
                 log_show_color(colors_enabled());
+
                 r = make_null_stdio();
                 if (r < 0)
-                        log_warning_errno(r, "Failed to redirect standard streams to /dev/null: %m");
+                        log_warning_errno(r, "Failed to redirect standard streams to /dev/null, ignoring: %m");
         }
 
         /* Mount /proc, /sys and friends, so that /proc/cmdline and
@@ -2429,10 +2429,10 @@ int main(int argc, char *argv[]) {
 finish:
         pager_close();
 
-        if (m)
+        if (m) {
                 arg_shutdown_watchdog = m->shutdown_watchdog;
-
-        m = manager_free(m);
+                m = manager_free(m);
+        }
 
         free_arguments();
         mac_selinux_finish();
@@ -2465,7 +2465,6 @@ finish:
 
         if (shutdown_verb) {
                 r = become_shutdown(shutdown_verb, retval);
-
                 log_error_errno(r, "Failed to execute shutdown binary, %s: %m", getpid_cached() == 1 ? "freezing" : "quitting");
                 error_message = "Failed to execute shutdown binary";
         }