core: in --user mode, report READY=1 as soon as basic.target is reached (#7102)
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 24 Oct 2017 12:48:54 +0000 (14:48 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 24 Oct 2017 12:48:54 +0000 (14:48 +0200)
When a user logs in, systemd-pam will wait for the user manager instance to
report readiness. We don't need to wait for all the jobs to finish, it
is enough if the basic startup is done and the user manager is responsive.

systemd --user will now send out a READY=1 notification when either of two
conditions becomes true:
- basic.target/start job is gone,
- the initial transaction is done.

Also fixes #2863.

TODO
src/core/manager.c
src/core/manager.h

diff --git a/TODO b/TODO
index 9abee50..e1771c8 100644 (file)
--- a/TODO
+++ b/TODO
@@ -325,8 +325,6 @@ Features:
 
 * introduce systemd-timesync-wait.service or so to sync on an NTP fix?
 
-* systemd --user should issue sd_notify() upon reaching basic.target, not on becoming idle
-
 * consider showing the unit names during boot up in the status output, not just the unit descriptions
 
 * maybe allow timer units with an empty Units= setting, so that they
index d2be218..3643deb 100644 (file)
@@ -2573,9 +2573,10 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) {
         m->n_reloading++;
 
         fprintf(f, "current-job-id=%"PRIu32"\n", m->current_job_id);
-        fprintf(f, "taint-usr=%s\n", yes_no(m->taint_usr));
         fprintf(f, "n-installed-jobs=%u\n", m->n_installed_jobs);
         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));
 
         dual_timestamp_serialize(f, "firmware-timestamp", &m->firmware_timestamp);
         dual_timestamp_serialize(f, "loader-timestamp", &m->loader_timestamp);
@@ -2732,6 +2733,15 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                         else
                                 m->taint_usr = m->taint_usr || b;
 
+                } else if ((val = startswith(l, "ready-sent="))) {
+                        int b;
+
+                        b = parse_boolean(val);
+                        if (b < 0)
+                                log_notice("Failed to parse ready-sent flag %s", val);
+                        else
+                                m->ready_sent = m->ready_sent || b;
+
                 } else if ((val = startswith(l, "firmware-timestamp=")))
                         dual_timestamp_deserialize(val, &m->firmware_timestamp);
                 else if ((val = startswith(l, "loader-timestamp=")))
@@ -3062,9 +3072,11 @@ static void manager_notify_finished(Manager *m) {
         bus_manager_send_finished(m, firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec);
 
         sd_notifyf(false,
-                   "READY=1\n"
-                   "STATUS=Startup finished in %s.",
+                   m->ready_sent ? "STATUS=Startup finished in %s."
+                                 : "READY=1\n"
+                                   "STATUS=Startup finished in %s.",
                    format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC));
+        m->ready_sent = true;
 }
 
 void manager_check_finished(Manager *m) {
@@ -3079,6 +3091,19 @@ 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) {
+                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;
+                }
+        }
+
         if (hashmap_size(m->jobs) > 0) {
                 if (m->jobs_in_progress_event_source)
                         /* Ignore any failure, this is only for feedback */
index 6fff7b2..ff69f6c 100644 (file)
@@ -254,6 +254,8 @@ struct Manager {
 
         bool taint_usr:1;
 
+        bool ready_sent:1;
+
         unsigned test_run_flags:8;
 
         /* If non-zero, exit with the following value when the systemd