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 3e3e867..65c7fc2 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 d97fe40..016741e 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 d044427..ad1ae59 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 92d5a0f..a6b2edc 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 fb28316..4555a4f 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_;