diff --git a/src/core/main.c b/src/core/main.c index c850f6f904..a088913f43 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -2218,25 +2218,6 @@ static void test_summary(Manager *m) { manager_dump_jobs(m, stdout, "\t"); } -static void log_taint_string(Manager *m) { - _cleanup_free_ char *taint = NULL; - - assert(m); - - if (!arg_system) - return; - - taint = manager_taint_string(m); - if (isempty(taint)) - return; - - log_struct(LOG_NOTICE, - LOG_MESSAGE("System is tainted: %s", taint), - "TAINT=%s", taint, - "MESSAGE_ID=" SD_MESSAGE_TAINTED_STR, - NULL); -} - static int collect_fds(FDSet **ret_fds, const char **ret_error_message) { int r; @@ -2550,8 +2531,6 @@ int main(int argc, char *argv[]) { "Loaded units and determined initial transaction in %s.", format_timespan(timespan, sizeof(timespan), after_startup - before_startup, 100 * USEC_PER_MSEC)); - log_taint_string(m); - if (arg_action == ACTION_TEST) { test_summary(m); retval = EXIT_SUCCESS; diff --git a/src/core/manager.c b/src/core/manager.c index f9222020eb..ee9ff15076 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -2658,6 +2658,7 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { fprintf(f, "n-failed-jobs=%u\n", m->n_failed_jobs); fprintf(f, "taint-usr=%s\n", yes_no(m->taint_usr)); fprintf(f, "ready-sent=%s\n", yes_no(m->ready_sent)); + fprintf(f, "taint-logged=%s\n", yes_no(m->taint_logged)); for (q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) { /* The userspace and finish timestamps only apply to the host system, hence only serialize them there */ @@ -2820,6 +2821,15 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { else m->ready_sent = m->ready_sent || b; + } else if ((val = startswith(l, "taint-logged="))) { + int b; + + b = parse_boolean(val); + if (b < 0) + log_notice("Failed to parse taint-logged flag %s", val); + else + m->taint_logged = m->taint_logged || b; + } else if (startswith(l, "env=")) { r = deserialize_environment(&m->environment, l); if (r == -ENOMEM) @@ -3077,6 +3087,27 @@ bool manager_unit_inactive_or_pending(Manager *m, const char *name) { return unit_inactive_or_pending(u); } +static void log_taint_string(Manager *m) { + _cleanup_free_ char *taint = NULL; + + assert(m); + + if (MANAGER_IS_USER(m) || m->taint_logged) + return; + + m->taint_logged = true; /* only check for taint once */ + + taint = manager_taint_string(m); + if (isempty(taint)) + return; + + log_struct(LOG_NOTICE, + LOG_MESSAGE("System is tainted: %s", taint), + "TAINT=%s", taint, + "MESSAGE_ID=" SD_MESSAGE_TAINTED_STR, + NULL); +} + static void manager_notify_finished(Manager *m) { char userspace[FORMAT_TIMESPAN_MAX], initrd[FORMAT_TIMESPAN_MAX], kernel[FORMAT_TIMESPAN_MAX], sum[FORMAT_TIMESPAN_MAX]; usec_t firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec; @@ -3149,6 +3180,8 @@ static void manager_notify_finished(Manager *m) { "STATUS=Startup finished in %s.", format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC)); m->ready_sent = true; + + log_taint_string(m); } void manager_check_finished(Manager *m) { @@ -3163,16 +3196,22 @@ void manager_check_finished(Manager *m) { if (m->exit_code != MANAGER_OK) return; - /* For user managers, send out READY=1 as soon as we reach basic.target */ - if (MANAGER_IS_USER(m) && !m->ready_sent) { + if (!m->ready_sent || !m->taint_logged) { Unit *u; u = manager_get_unit(m, SPECIAL_BASIC_TARGET); if (u && !u->job) { - sd_notifyf(false, - "READY=1\n" - "STATUS=Reached " SPECIAL_BASIC_TARGET "."); - m->ready_sent = true; + /* Log the taint string as soon as we reach basic.target */ + log_taint_string(m); + + /* For user managers, send out READY=1 as soon as we reach basic.target */ + if (MANAGER_IS_USER(m) && !m->ready_sent) { + sd_notifyf(false, + "READY=1\n" + "STATUS=Reached " SPECIAL_BASIC_TARGET "."); + + m->ready_sent = true; + } } } diff --git a/src/core/manager.h b/src/core/manager.h index 902af2609d..1531374d1c 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -261,8 +261,12 @@ struct Manager { bool taint_usr:1; + /* Have we already sent out the READY=1 notification? */ bool ready_sent:1; + /* Have we already printed the taint line if necessary? */ + bool taint_logged:1; + unsigned test_run_flags:8; /* If non-zero, exit with the following value when the systemd