]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: delay logging the taint string until after basic.target is reached (#7935)
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 21 Jan 2018 12:17:54 +0000 (23:17 +1100)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 21 Jan 2018 12:17:54 +0000 (21:17 +0900)
This happens to be almost the same moment as when we send READY=1 in the user
instance, but the logic is slightly different, since we log taint when
basic.target is reached in the system manager, but we send the notification
only in the user manager. So add a separate flag for this and propagate it
across reloads.

Fixes #7683.

src/core/main.c
src/core/manager.c
src/core/manager.h

index c850f6f904f1548cadbc7dd842fab48fb7f7a261..a088913f43a4358775b73a60589f8ad77d5c1ff8 100644 (file)
@@ -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;
index f9222020ebc7ea3d3dad6a4303fa4a7c59f46c42..ee9ff15076e847a3f0565303e9d41c3567b2328e 100644 (file)
@@ -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;
+                        }
                 }
         }
 
index 902af2609da70b6607a80b43b4b563c1a39c9ffe..1531374d1c0ff8b5b43c7622fe8861578c87a338 100644 (file)
@@ -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