chiark / gitweb /
systemd: do not output status messages once gettys are running
[elogind.git] / src / core / manager.c
index 612819442726341567174fd8f65fbe8f6fc4002c..ad1a8d61797b708d01ec40fd4633a0865d853b57 100644 (file)
@@ -273,6 +273,58 @@ static void manager_print_jobs_in_progress(Manager *m) {
         m->jobs_in_progress_iteration++;
 }
 
+static int manager_watch_idle_pipe(Manager *m) {
+        struct epoll_event ev = {
+                .events = EPOLLIN,
+                .data.ptr = &m->idle_pipe_watch,
+        };
+        int r;
+
+        if (m->idle_pipe_watch.type != WATCH_INVALID)
+                return 0;
+
+        if (m->idle_pipe[2] < 0)
+                return 0;
+
+        m->idle_pipe_watch.type = WATCH_IDLE_PIPE;
+        m->idle_pipe_watch.fd = m->idle_pipe[2];
+        if (m->idle_pipe_watch.fd < 0) {
+                log_error("Failed to create timerfd: %m");
+                r = -errno;
+                goto err;
+        }
+
+        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->idle_pipe_watch.fd, &ev) < 0) {
+                log_error("Failed to add idle_pipe fd to epoll: %m");
+                r = -errno;
+                goto err;
+        }
+
+        log_debug("Set up idle_pipe watch.");
+        log_debug("m->epoll_fd=%d m->idle_pipe_watch.fd=%d",
+                  m->epoll_fd, m->idle_pipe_watch.fd);
+
+        return 0;
+
+err:
+        if (m->idle_pipe_watch.fd >= 0)
+                close_nointr_nofail(m->idle_pipe_watch.fd);
+        watch_init(&m->idle_pipe_watch);
+        return r;
+}
+
+static void manager_unwatch_idle_pipe(Manager *m) {
+        if (m->idle_pipe_watch.type != WATCH_IDLE_PIPE)
+                return;
+
+        log_debug("m->epoll_fd=%d m->idle_pipe_watch.fd=%d",
+                  m->epoll_fd, m->idle_pipe_watch.fd);
+        assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, m->idle_pipe_watch.fd, NULL) >= 0);
+        watch_init(&m->idle_pipe_watch);
+
+        log_debug("Closed idle_pipe watch.");
+}
+
 static int manager_setup_time_change(Manager *m) {
         struct epoll_event ev = {
                 .events = EPOLLIN,
@@ -424,7 +476,7 @@ static void manager_strip_environment(Manager *m) {
         strv_env_clean(m->environment);
 }
 
-int manager_new(SystemdRunningAs running_as, Manager **_m) {
+int manager_new(SystemdRunningAs running_as, bool reexecuting, Manager **_m) {
         Manager *m;
         int r = -ENOMEM;
 
@@ -445,7 +497,7 @@ int manager_new(SystemdRunningAs running_as, Manager **_m) {
         m->name_data_slot = m->conn_data_slot = m->subscribed_data_slot = -1;
         m->exit_code = _MANAGER_EXIT_CODE_INVALID;
         m->pin_cgroupfs_fd = -1;
-        m->idle_pipe[0] = m->idle_pipe[1] = -1;
+        m->idle_pipe[0] = m->idle_pipe[1] = m->idle_pipe[2] = m->idle_pipe[3] = -1;
 
         watch_init(&m->signal_watch);
         watch_init(&m->mount_watch);
@@ -476,7 +528,8 @@ int manager_new(SystemdRunningAs running_as, Manager **_m) {
         if (!m->cgroup_unit)
                 goto fail;
 
-        if (!(m->watch_bus = hashmap_new(string_hash_func, string_compare_func)))
+        m->watch_bus = hashmap_new(string_hash_func, string_compare_func);
+        if (!m->watch_bus)
                 goto fail;
 
         m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
@@ -502,7 +555,7 @@ int manager_new(SystemdRunningAs running_as, Manager **_m) {
         /* Try to connect to the busses, if possible. */
         if ((running_as == SYSTEMD_USER && getenv("DBUS_SESSION_BUS_ADDRESS")) ||
             running_as == SYSTEMD_SYSTEM) {
-                r = bus_init(m, running_as != SYSTEMD_SYSTEM);
+                r = bus_init(m, reexecuting || running_as != SYSTEMD_SYSTEM);
                 if (r < 0)
                         goto fail;
         } else
@@ -656,6 +709,11 @@ static void manager_clear_jobs_and_units(Manager *m) {
         m->n_running_jobs = 0;
 }
 
+static void close_idle_pipe(Manager *m) {
+        close_pipe(m->idle_pipe);
+        close_pipe(m->idle_pipe + 2);
+}
+
 void manager_free(Manager *m) {
         UnitType c;
         int i;
@@ -700,7 +758,7 @@ void manager_free(Manager *m) {
         hashmap_free(m->cgroup_unit);
         set_free_free(m->unit_path_cache);
 
-        close_pipe(m->idle_pipe);
+        close_idle_pipe(m);
 
         free(m->switch_root);
         free(m->switch_root_init);
@@ -863,6 +921,11 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
         if (serialization) {
                 assert(m->n_reloading > 0);
                 m->n_reloading --;
+
+                /* Let's wait for the UnitNew/JobNew messages being
+                 * sent, before we notify that the reload is
+                 * finished */
+                m->send_reloading_done = true;
         }
 
         return r;
@@ -1132,6 +1195,9 @@ unsigned manager_dispatch_run_queue(Manager *m) {
         if (m->n_running_jobs > 0)
                 manager_watch_jobs_in_progress(m);
 
+        if (m->n_on_console > 0)
+                manager_watch_idle_pipe(m);
+
         return n;
 }
 
@@ -1162,6 +1228,13 @@ unsigned manager_dispatch_dbus_queue(Manager *m) {
         }
 
         m->dispatching_dbus_queue = false;
+
+        if (m->send_reloading_done) {
+                m->send_reloading_done = false;
+
+                bus_broadcast_reloading(m, false);
+        }
+
         return n;
 }
 
@@ -1678,6 +1751,14 @@ static int process_event(Manager *m, struct epoll_event *ev) {
                 break;
         }
 
+        case WATCH_IDLE_PIPE: {
+                m->no_console_output = true;
+
+                manager_unwatch_idle_pipe(m);
+                close_idle_pipe(m);
+                break;
+        }
+
         default:
                 log_error("event type=%i", w->type);
                 assert_not_reached("Unknown epoll event type.");
@@ -2041,6 +2122,8 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) {
                 }
         }
 
+        bus_serialize(m, f);
+
         fputc('\n', f);
 
         HASHMAP_FOREACH_KEY(u, t, m->units, i) {
@@ -2054,7 +2137,8 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) {
                 fputs(u->id, f);
                 fputc('\n', f);
 
-                if ((r = unit_serialize(u, f, fds, !switching_root)) < 0) {
+                r = unit_serialize(u, f, fds, !switching_root);
+                if (r < 0) {
                         m->n_reloading --;
                         return r;
                 }
@@ -2159,7 +2243,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
 
                         strv_free(m->environment);
                         m->environment = e;
-                } else
+                } else if (bus_deserialize_item(m, l) == 0)
                         log_debug("Unknown serialization item '%s'", l);
         }
 
@@ -2234,6 +2318,7 @@ int manager_reload(Manager *m) {
                 return r;
 
         m->n_reloading ++;
+        bus_broadcast_reloading(m, true);
 
         fds = fdset_new();
         if (!fds) {
@@ -2293,6 +2378,8 @@ int manager_reload(Manager *m) {
         assert(m->n_reloading > 0);
         m->n_reloading--;
 
+        m->send_reloading_done = true;
+
 finish:
         if (f)
                 fclose(f);
@@ -2365,7 +2452,8 @@ void manager_check_finished(Manager *m) {
         }
 
         /* Notify Type=idle units that we are done now */
-        close_pipe(m->idle_pipe);
+        manager_unwatch_idle_pipe(m);
+        close_idle_pipe(m);
 
         /* Turn off confirm spawn now */
         m->confirm_spawn = false;
@@ -2641,6 +2729,9 @@ static bool manager_get_show_status(Manager *m) {
         if (m->running_as != SYSTEMD_SYSTEM)
                 return false;
 
+        if (m->no_console_output)
+                return false;
+
         if (m->show_status)
                 return true;