]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
pid1: preserve current value of log target across re-{load,execution}
authorFranck Bui <fbui@suse.com>
Fri, 1 Jun 2018 16:21:03 +0000 (18:21 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 13 Jun 2018 16:52:27 +0000 (18:52 +0200)
To make debugging easier, this patches allows one to change the log target and
do reload/reexec without modifying configuration permanently, which makes
debugging easier.

Indeed if one changed the log target at runtime (via the bus or via signals),
the change was lost on the next reload/reexecution.

In order to restore back the default value (set via system.conf, environment
variables or any other means ), the empty string in the "LogTarget" property is
now supported as well as sending SIGTRMIN+26 signal.

man/systemd.xml
src/core/dbus-manager.c
src/core/main.c
src/core/manager.c
src/core/manager.h

index 3e3e8678bc1d714516f410c6a949a8ff21ae38b2..65c7fc2bb120a071711ad5e409ec4d123bb57ff3 100644 (file)
 
       <varlistentry>
         <term><constant>SIGRTMIN+26</constant></term>
+
+        <listitem><para>Restores the log target to its configured value. The configured value is derived from – in
+        order of priority – the value specified with <varname>systemd.log-target=</varname> on the kernel command line,
+        or the value specified with <option>LogTarget=</option> in the configuration file, or the built-in
+        default.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
         <term><constant>SIGRTMIN+27</constant></term>
         <term><constant>SIGRTMIN+28</constant></term>
 
-        <listitem><para>Sets the log target to
-        <literal>journal-or-kmsg</literal> (or
-        <literal>console</literal> on
-        <constant>SIGRTMIN+27</constant>, <literal>kmsg</literal> on
-        <constant>SIGRTMIN+28</constant>), as controlled via
-        <varname>systemd.log_target=journal-or-kmsg</varname> (or
-        <varname>systemd.log_target=console</varname> on
-        <constant>SIGRTMIN+27</constant> or
-        <varname>systemd.log_target=kmsg</varname> on
-        <constant>SIGRTMIN+28</constant>) on the kernel command
-        line.</para></listitem>
+        <listitem><para>Sets the log target to <literal>console</literal> on <constant>SIGRTMIN+27</constant> (or
+        <literal>kmsg</literal> on <constant>SIGRTMIN+28</constant>), in a fashion equivalent to
+        <varname>systemd.log_target=console</varname> (or <varname>systemd.log_target=kmsg</varname> on
+        <constant>SIGRTMIN+28</constant>) on the kernel command line.</para></listitem>
       </varlistentry>
     </variablelist>
   </refsect1>
index d97fe4087cd1c55bb27f42eacbdf796ebe96d40b..016741e40b5929ed420d03d2a976dac4b4fac94e 100644 (file)
@@ -114,6 +114,7 @@ static int property_set_log_target(
                 void *userdata,
                 sd_bus_error *error) {
 
+        Manager *m = userdata;
         const char *t;
         int r;
 
@@ -124,7 +125,19 @@ static int property_set_log_target(
         if (r < 0)
                 return r;
 
-        return log_set_target_from_string(t);
+        if (isempty(t))
+                manager_restore_original_log_target(m);
+        else {
+                LogTarget target;
+
+                target = log_target_from_string(t);
+                if (target < 0)
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid log target '%s'", t);
+
+                manager_override_log_target(m, target);
+        }
+
+        return 0;
 }
 
 static int property_get_log_level(
index d044427d7457f95912d795d93aa5a085d9f6f798..ad1ae591e1e3191f87e734e54b2dbc96c5e9a4ac 100644 (file)
@@ -1641,11 +1641,16 @@ static int invoke_main_loop(
                 switch (m->exit_code) {
 
                 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)
@@ -1655,6 +1660,8 @@ static int invoke_main_loop(
 
                         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)
index 92d5a0fff6fbff8e0af45015234c33ab6e76119e..a6b2edcb83ffe527e56ef34e2b5b30e3c2bea1e0 100644 (file)
@@ -737,6 +737,7 @@ int manager_new(UnitFileScope scope, unsigned test_run_flags, Manager **_m) {
         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;
 
 #if ENABLE_EFI
         if (MANAGER_IS_SYSTEM(m) && detect_container() <= 0)
@@ -2646,18 +2647,15 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
 
                 case 26:
                 case 29: /* compatibility: used to be mapped to LOG_TARGET_SYSLOG_OR_KMSG */
-                        log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
-                        log_notice("Setting log target to journal-or-kmsg.");
+                        manager_restore_original_log_target(m);
                         break;
 
                 case 27:
-                        log_set_target(LOG_TARGET_CONSOLE);
-                        log_notice("Setting log target to console.");
+                        manager_override_log_target(m, LOG_TARGET_CONSOLE);
                         break;
 
                 case 28:
-                        log_set_target(LOG_TARGET_KMSG);
-                        log_notice("Setting log target to kmsg.");
+                        manager_override_log_target(m, LOG_TARGET_KMSG);
                         break;
 
                 default:
@@ -3029,6 +3027,8 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) {
 
         if (m->log_level_overridden)
                 fprintf(f, "log-level-override=%i\n", log_get_max_level());
+        if (m->log_target_overridden)
+                fprintf(f, "log-target-override=%s\n", log_target_to_string(log_get_target()));
 
         for (q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) {
                 /* The userspace and finish timestamps only apply to the host system, hence only serialize them there */
@@ -3222,6 +3222,15 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                         else
                                 manager_override_log_level(m, level);
 
+                } else if ((val = startswith(l, "log-target-override="))) {
+                        LogTarget target;
+
+                        target = log_target_from_string(val);
+                        if (target < 0)
+                                log_notice("Failed to parse log-target-override value '%s', ignoring.", val);
+                        else
+                                manager_override_log_target(m, target);
+
                 } else if (startswith(l, "env=")) {
                         r = deserialize_environment(&m->environment, l);
                         if (r == -ENOMEM)
@@ -4489,6 +4498,30 @@ void manager_restore_original_log_level(Manager *m) {
         m->log_level_overridden = false;
 }
 
+void manager_override_log_target(Manager *m, LogTarget target) {
+        assert(m);
+
+        if (!m->log_target_overridden) {
+                m->original_log_target = log_get_target();
+                m->log_target_overridden = true;
+        }
+
+        log_info("Setting log target to %s.", log_target_to_string(target));
+        log_set_target(target);
+}
+
+void manager_restore_original_log_target(Manager *m) {
+        assert(m);
+
+        if (!m->log_target_overridden)
+                return;
+
+        log_info("Restoring log target to original %s.", log_target_to_string(m->original_log_target));
+
+        log_set_target(m->original_log_target);
+        m->log_target_overridden = false;
+}
+
 static const char *const manager_state_table[_MANAGER_STATE_MAX] = {
         [MANAGER_INITIALIZING] = "initializing",
         [MANAGER_STARTING] = "starting",
index fb28316b8e5cb33bb469b525b656bd9f0bd969e6..4555a4ff1523eb34b8cc1fda5d5a2789df51ce16 100644 (file)
@@ -303,7 +303,9 @@ struct Manager {
         usec_t default_timer_accuracy_usec;
 
         int original_log_level;
+        LogTarget original_log_target;
         bool log_level_overridden:1;
+        bool log_target_overridden:1;
 
         struct rlimit *rlimit[_RLIMIT_MAX];
 
@@ -471,6 +473,9 @@ void manager_unref_console(Manager *m);
 void manager_override_log_level(Manager *m, int level);
 void manager_restore_original_log_level(Manager *m);
 
+void manager_override_log_target(Manager *m, LogTarget target);
+void manager_restore_original_log_target(Manager *m);
+
 const char *manager_state_to_string(ManagerState m) _const_;
 ManagerState manager_state_from_string(const char *s) _pure_;