chiark / gitweb /
util: make time formatting a bit smarter
[elogind.git] / src / core / manager.c
index ec12a753719b1bc9dff6fef659ea3463d3f51ebc..f90ccd5b5feec7ffbf583f274cdee605727b02e9 100644 (file)
@@ -95,7 +95,7 @@ static int manager_setup_notify(Manager *m) {
                 struct sockaddr_un un;
         } sa;
         struct epoll_event ev;
-        int one = 1;
+        int one = 1, r;
 
         assert(m);
 
@@ -116,12 +116,15 @@ static int manager_setup_notify(Manager *m) {
 
         sa.un.sun_path[0] = 0;
 
-        if (bind(m->notify_watch.fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) {
+        r = bind(m->notify_watch.fd, &sa.sa,
+                 offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1));
+        if (r < 0) {
                 log_error("bind() failed: %m");
                 return -errno;
         }
 
-        if (setsockopt(m->notify_watch.fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0) {
+        r = setsockopt(m->notify_watch.fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
+        if (r < 0) {
                 log_error("SO_PASSCRED failed: %m");
                 return -errno;
         }
@@ -130,7 +133,8 @@ static int manager_setup_notify(Manager *m) {
         ev.events = EPOLLIN;
         ev.data.ptr = &m->notify_watch;
 
-        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->notify_watch.fd, &ev) < 0) {
+        r = epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->notify_watch.fd, &ev);
+        if (r < 0) {
                 log_error("Failed to add notification socket fd to epoll: %m");
                 return -errno;
         }
@@ -148,6 +152,9 @@ static int manager_setup_notify(Manager *m) {
 static int manager_jobs_in_progress_mod_timer(Manager *m) {
         struct itimerspec its;
 
+        if (m->jobs_in_progress_watch.type != WATCH_JOBS_IN_PROGRESS)
+                return 0;
+
         zero(its);
 
         its.it_value.tv_sec = JOBS_IN_PROGRESS_WAIT_SEC;
@@ -223,36 +230,26 @@ static void draw_cylon(char buffer[], size_t buflen, unsigned width, unsigned po
         assert(pos <= width+1); /* 0 or width+1 mean that the center light is behind the corner */
 
         if (pos > 1) {
-                if (pos > 2) {
-                        memset(p, ' ', pos-2);
-                        p += pos-2;
-                }
-                memcpy(p, ANSI_RED_ON, strlen(ANSI_RED_ON));
-                p += strlen(ANSI_RED_ON);
+                if (pos > 2)
+                        p = mempset(p, ' ', pos-2);
+                p = stpcpy(p, ANSI_RED_ON);
                 *p++ = '*';
         }
 
         if (pos > 0 && pos <= width) {
-                memcpy(p, ANSI_HIGHLIGHT_RED_ON, strlen(ANSI_HIGHLIGHT_RED_ON));
-                p += strlen(ANSI_HIGHLIGHT_RED_ON);
+                p = stpcpy(p, ANSI_HIGHLIGHT_RED_ON);
                 *p++ = '*';
         }
 
-        memcpy(p, ANSI_HIGHLIGHT_OFF, strlen(ANSI_HIGHLIGHT_OFF));
-        p += strlen(ANSI_HIGHLIGHT_OFF);
+        p = stpcpy(p, ANSI_HIGHLIGHT_OFF);
 
         if (pos < width) {
-                memcpy(p, ANSI_RED_ON, strlen(ANSI_RED_ON));
-                p += strlen(ANSI_RED_ON);
+                p = stpcpy(p, ANSI_RED_ON);
                 *p++ = '*';
-                if (pos < width-1) {
-                        memset(p, ' ', width-1-pos);
-                        p += width-1-pos;
-                }
-                memcpy(p, ANSI_HIGHLIGHT_OFF, strlen(ANSI_HIGHLIGHT_OFF));
-                p += strlen(ANSI_HIGHLIGHT_OFF);
+                if (pos < width-1)
+                        p = mempset(p, ' ', width-1-pos);
+                p = stpcpy(p, ANSI_HIGHLIGHT_OFF);
         }
-        *p = 0;
 }
 
 static void manager_print_jobs_in_progress(Manager *m) {
@@ -269,6 +266,10 @@ static void manager_print_jobs_in_progress(Manager *m) {
                 if (j->state == JOB_RUNNING && counter++ == print_nr)
                         break;
 
+        /* m->n_running_jobs must be consistent with the contents of m->jobs,
+         * so the above loop must have succeeded in finding j. */
+        assert(counter == print_nr + 1);
+
         cylon_pos = m->jobs_in_progress_iteration % 14;
         if (cylon_pos >= 8)
                 cylon_pos = 14 - cylon_pos;
@@ -675,6 +676,9 @@ static void manager_clear_jobs_and_units(Manager *m) {
 
         assert(hashmap_isempty(m->jobs));
         assert(hashmap_isempty(m->units));
+
+        m->n_on_console = 0;
+        m->n_running_jobs = 0;
 }
 
 void manager_free(Manager *m) {
@@ -1137,7 +1141,7 @@ unsigned manager_dispatch_run_queue(Manager *m) {
 
         m->dispatching_run_queue = false;
 
-        if (hashmap_size(m->jobs) > 0)
+        if (m->n_running_jobs > 0)
                 manager_watch_jobs_in_progress(m);
 
         return n;
@@ -1188,7 +1192,7 @@ static int manager_process_notify_fd(Manager *m) {
                         uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
                 } control;
                 Unit *u;
-                char **tags;
+                char _cleanup_strv_free_ **tags = NULL;
 
                 zero(iovec);
                 iovec.iov_base = buf;
@@ -1241,8 +1245,6 @@ static int manager_process_notify_fd(Manager *m) {
 
                 if (UNIT_VTABLE(u)->notify_message)
                         UNIT_VTABLE(u)->notify_message(u, ucred->pid, tags);
-
-                strv_free(tags);
         }
 
         return 0;
@@ -1667,6 +1669,8 @@ static int process_event(Manager *m, struct epoll_event *ev) {
                            NULL);
 
                 /* Restart the watch */
+                epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, m->time_change_watch.fd,
+                          NULL);
                 close_nointr_nofail(m->time_change_watch.fd);
                 watch_init(&m->time_change_watch);
                 manager_setup_time_change(m);
@@ -1896,7 +1900,8 @@ void manager_send_unit_plymouth(Manager *m, Unit *u) {
 
         /* We set SOCK_NONBLOCK here so that we rather drop the
          * message then wait for plymouth */
-        if ((fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0)) < 0) {
+        fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+        if (fd < 0) {
                 log_error("socket() failed: %m");
                 return;
         }
@@ -2331,6 +2336,12 @@ static bool manager_is_booting_or_shutting_down(Manager *m) {
         return false;
 }
 
+bool manager_is_reloading_or_reexecuting(Manager *m) {
+        assert(m);
+
+        return m->n_reloading != 0;
+}
+
 void manager_reset_failed(Manager *m) {
         Unit *u;
         Iterator i;
@@ -2361,6 +2372,9 @@ void manager_check_finished(Manager *m) {
 
         assert(m);
 
+        if (m->n_running_jobs == 0)
+                manager_unwatch_jobs_in_progress(m);
+
         if (hashmap_size(m->jobs) > 0) {
                 manager_jobs_in_progress_mod_timer(m);
                 return;
@@ -2372,8 +2386,6 @@ void manager_check_finished(Manager *m) {
         /* Turn off confirm spawn now */
         m->confirm_spawn = false;
 
-        manager_unwatch_jobs_in_progress(m);
-
         if (dual_timestamp_is_set(&m->finish_timestamp))
                 return;
 
@@ -2403,10 +2415,10 @@ void manager_check_finished(Manager *m) {
                                            "INITRD_USEC=%llu", (unsigned long long) initrd_usec,
                                            "USERSPACE_USEC=%llu", (unsigned long long) userspace_usec,
                                            "MESSAGE=Startup finished in %s (kernel) + %s (initrd) + %s (userspace) = %s.",
-                                           format_timespan(kernel, sizeof(kernel), kernel_usec),
-                                           format_timespan(initrd, sizeof(initrd), initrd_usec),
-                                           format_timespan(userspace, sizeof(userspace), userspace_usec),
-                                           format_timespan(sum, sizeof(sum), total_usec),
+                                           format_timespan(kernel, sizeof(kernel), kernel_usec, USEC_PER_MSEC),
+                                           format_timespan(initrd, sizeof(initrd), initrd_usec, USEC_PER_MSEC),
+                                           format_timespan(userspace, sizeof(userspace), userspace_usec, USEC_PER_MSEC),
+                                           format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC),
                                            NULL);
                 } else {
                         kernel_usec = m->userspace_timestamp.monotonic - m->kernel_timestamp.monotonic;
@@ -2418,9 +2430,9 @@ void manager_check_finished(Manager *m) {
                                            "KERNEL_USEC=%llu", (unsigned long long) kernel_usec,
                                            "USERSPACE_USEC=%llu", (unsigned long long) userspace_usec,
                                            "MESSAGE=Startup finished in %s (kernel) + %s (userspace) = %s.",
-                                           format_timespan(kernel, sizeof(kernel), kernel_usec),
-                                           format_timespan(userspace, sizeof(userspace), userspace_usec),
-                                           format_timespan(sum, sizeof(sum), total_usec),
+                                           format_timespan(kernel, sizeof(kernel), kernel_usec, USEC_PER_MSEC),
+                                           format_timespan(userspace, sizeof(userspace), userspace_usec, USEC_PER_MSEC),
+                                           format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC),
                                            NULL);
                 }
         } else {
@@ -2432,7 +2444,7 @@ void manager_check_finished(Manager *m) {
                                    MESSAGE_ID(SD_MESSAGE_STARTUP_FINISHED),
                                    "USERSPACE_USEC=%llu", (unsigned long long) userspace_usec,
                                    "MESSAGE=Startup finished in %s.",
-                                   format_timespan(sum, sizeof(sum), total_usec),
+                                   format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC),
                                    NULL);
         }
 
@@ -2440,7 +2452,7 @@ void manager_check_finished(Manager *m) {
 
         sd_notifyf(false,
                    "READY=1\nSTATUS=Startup finished in %s.",
-                   format_timespan(sum, sizeof(sum), total_usec));
+                   format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC));
 }
 
 static int create_generator_dir(Manager *m, char **generator, const char *name) {
@@ -2473,9 +2485,9 @@ static int create_generator_dir(Manager *m, char **generator, const char *name)
                         return log_oom();
 
                 if (!mkdtemp(p)) {
-                        free(p);
                         log_error("Failed to create generator directory %s: %m",
                                   p);
+                        free(p);
                         return -errno;
                 }
         }