pid1: preserve current value of log target across re-{load,execution}

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.
This commit is contained in:
Franck Bui 2018-06-01 18:21:03 +02:00 committed by Lennart Poettering
parent a6ecbf836c
commit bda7d78ba1
5 changed files with 77 additions and 18 deletions

View file

@ -772,20 +772,21 @@
<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>

View 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(

View 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)

View 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",

View 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_;