]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #27769 from YHNdnzj/loginctl-followup
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 24 May 2023 20:52:06 +0000 (05:52 +0900)
committerGitHub <noreply@github.com>
Wed, 24 May 2023 20:52:06 +0000 (05:52 +0900)
loginctl: some follow-ups

35 files changed:
src/analyze/analyze-critical-chain.c
src/analyze/analyze-plot.c
src/analyze/analyze-time-data.c
src/basic/string-util.c
src/basic/strv.c
src/core/automount.c
src/core/device.c
src/core/mount.c
src/core/path.c
src/core/scope.c
src/core/service.c
src/core/service.h
src/core/slice.c
src/core/socket.c
src/core/swap.c
src/core/target.c
src/core/timer.c
src/core/unit.c
src/core/unit.h
src/coredump/coredump-vacuum.c
src/journal-remote/journal-upload.c
src/journal/journald-native.c
src/libsystemd-network/lldp-neighbor.c
src/libsystemd-network/sd-dhcp-lease.c
src/libsystemd/sd-bus/bus-control.c
src/libsystemd/sd-bus/bus-socket.c
src/libsystemd/sd-login/sd-login.c
src/libsystemd/sd-resolve/sd-resolve.c
src/nspawn/nspawn-network.c
src/shared/calendarspec.c
src/system-update-generator/system-update-generator.c
src/ukify/ukify.py
src/update-utmp/update-utmp.c
test/units/testsuite-01.service
test/units/testsuite-01.sh

index f80f3ddb63c2e2ae7d05f5ebf6c76ab2c8f88687..4a7f452eaf5f375da440b06e8a5baf539610b142 100644 (file)
@@ -29,7 +29,7 @@ static int list_dependencies_print(
         printf("%s", special_glyph(last ? SPECIAL_GLYPH_TREE_RIGHT : SPECIAL_GLYPH_TREE_BRANCH));
 
         if (times) {
-                if (times->time > 0)
+                if (timestamp_is_set(times->time))
                         printf("%s%s @%s +%s%s", ansi_highlight_red(), name,
                                FORMAT_TIMESPAN(times->activating - boot->userspace_time, USEC_PER_MSEC),
                                FORMAT_TIMESPAN(times->time, USEC_PER_MSEC), ansi_normal());
index ef40e64631d5d268aec0d7ac3b831d0dc8498359..0fbe17465e06a34cf57c5f6c0802619f86a8c217 100644 (file)
@@ -206,14 +206,14 @@ static int produce_plot_as_svg(
 
         if (boot->firmware_time > boot->loader_time)
                 m++;
-        if (boot->loader_time > 0) {
+        if (timestamp_is_set(boot->loader_time)) {
                 m++;
                 if (width < 1000.0)
                         width = 1000.0;
         }
-        if (boot->initrd_time > 0)
+        if (timestamp_is_set(boot->initrd_time))
                 m++;
-        if (boot->kernel_done_time > 0)
+        if (timestamp_is_set(boot->kernel_done_time))
                 m++;
 
         for (u = times; u->has_data; u++) {
@@ -295,22 +295,22 @@ static int produce_plot_as_svg(
         svg("<g transform=\"translate(%.3f,100)\">\n", 20.0 + (SCALE_X * boot->firmware_time));
         svg_graph_box(m, -(double) boot->firmware_time, boot->finish_time);
 
-        if (boot->firmware_time > 0) {
+        if (timestamp_is_set(boot->firmware_time)) {
                 svg_bar("firmware", -(double) boot->firmware_time, -(double) boot->loader_time, y);
                 svg_text(true, -(double) boot->firmware_time, y, "firmware");
                 y++;
         }
-        if (boot->loader_time > 0) {
+        if (timestamp_is_set(boot->loader_time)) {
                 svg_bar("loader", -(double) boot->loader_time, 0, y);
                 svg_text(true, -(double) boot->loader_time, y, "loader");
                 y++;
         }
-        if (boot->kernel_done_time > 0) {
+        if (timestamp_is_set(boot->kernel_done_time)) {
                 svg_bar("kernel", 0, boot->kernel_done_time, y);
                 svg_text(true, 0, y, "kernel");
                 y++;
         }
-        if (boot->initrd_time > 0) {
+        if (timestamp_is_set(boot->initrd_time)) {
                 svg_bar("initrd", boot->initrd_time, boot->userspace_time, y);
                 if (boot->initrd_security_start_time < boot->initrd_security_finish_time)
                         svg_bar("security", boot->initrd_security_start_time, boot->initrd_security_finish_time, y);
@@ -330,7 +330,7 @@ static int produce_plot_as_svg(
         }
 
         svg_bar("active", boot->userspace_time, boot->finish_time, y);
-        if (boot->security_start_time > 0)
+        if (timestamp_is_set(boot->security_start_time))
                 svg_bar("security", boot->security_start_time, boot->security_finish_time, y);
         svg_bar("generators", boot->generators_start_time, boot->generators_finish_time, y);
         svg_bar("unitsload", boot->unitsload_start_time, boot->unitsload_finish_time, y);
@@ -354,7 +354,7 @@ static int produce_plot_as_svg(
         svg_bar("deactivating", 0, 300000, y);
         svg_text(true, 400000, y, "Deactivating");
         y++;
-        if (boot->security_start_time > 0) {
+        if (timestamp_is_set(boot->security_start_time)) {
                 svg_bar("security", 0, 300000, y);
                 svg_text(true, 400000, y, "Setting up security module");
                 y++;
index baee3cedbb531985f5ee9f9fa31374efccbebb34..70717fc4b27d99f5f6e4c41ec7dc9329259de449 100644 (file)
@@ -173,24 +173,24 @@ int pretty_boot_time(sd_bus *bus, char **ret) {
         if (!text)
                 return log_oom();
 
-        if (t->firmware_time > 0 && !strextend(&text, FORMAT_TIMESPAN(t->firmware_time - t->loader_time, USEC_PER_MSEC), " (firmware) + "))
+        if (timestamp_is_set(t->firmware_time) && !strextend(&text, FORMAT_TIMESPAN(t->firmware_time - t->loader_time, USEC_PER_MSEC), " (firmware) + "))
                 return log_oom();
-        if (t->loader_time > 0 && !strextend(&text, FORMAT_TIMESPAN(t->loader_time, USEC_PER_MSEC), " (loader) + "))
+        if (timestamp_is_set(t->loader_time) && !strextend(&text, FORMAT_TIMESPAN(t->loader_time, USEC_PER_MSEC), " (loader) + "))
                 return log_oom();
-        if (t->kernel_done_time > 0 && !strextend(&text, FORMAT_TIMESPAN(t->kernel_done_time, USEC_PER_MSEC), " (kernel) + "))
+        if (timestamp_is_set(t->kernel_done_time) && !strextend(&text, FORMAT_TIMESPAN(t->kernel_done_time, USEC_PER_MSEC), " (kernel) + "))
                 return log_oom();
-        if (t->initrd_time > 0 && !strextend(&text, FORMAT_TIMESPAN(t->userspace_time - t->initrd_time, USEC_PER_MSEC), " (initrd) + "))
+        if (timestamp_is_set(t->initrd_time) && !strextend(&text, FORMAT_TIMESPAN(t->userspace_time - t->initrd_time, USEC_PER_MSEC), " (initrd) + "))
                 return log_oom();
 
         if (!strextend(&text, FORMAT_TIMESPAN(t->finish_time - t->userspace_time, USEC_PER_MSEC), " (userspace) "))
                 return log_oom();
 
-        if (t->kernel_done_time > 0)
+        if (timestamp_is_set(t->kernel_done_time))
                 if (!strextend(&text, "= ", FORMAT_TIMESPAN(t->firmware_time + t->finish_time, USEC_PER_MSEC),  " "))
                         return log_oom();
 
         if (unit_id && timestamp_is_set(activated_time)) {
-                usec_t base = t->userspace_time > 0 ? t->userspace_time : t->reverse_offset;
+                usec_t base = timestamp_is_set(t->userspace_time) ? t->userspace_time : t->reverse_offset;
 
                 if (!strextend(&text, "\n", unit_id, " reached after ", FORMAT_TIMESPAN(activated_time - base, USEC_PER_MSEC), " in userspace."))
                         return log_oom();
index c74ee67dfec24c7d08eb11051d2b4887d98a493d..d4141968df34c4ad74be14c019f8704004a18926 100644 (file)
@@ -955,8 +955,7 @@ int free_and_strdup(char **p, const char *s) {
         } else
                 t = NULL;
 
-        free(*p);
-        *p = t;
+        free_and_replace(*p, t);
 
         return 1;
 }
index 822dadeeb4a1bcdedbbfa9fc8b94344553c713d5..deadb9909e99b7643a0934043200b7c48cbe596e 100644 (file)
@@ -723,8 +723,7 @@ char** strv_shell_escape(char **l, const char *bad) {
                 if (!v)
                         return NULL;
 
-                free(*s);
-                *s = v;
+                free_and_replace(*s, v);
         }
 
         return l;
index 89755e3a9b354320679aa3c550317993d3e626b4..5df697bf22080e506aa24614e6484a684f636290 100644 (file)
@@ -283,7 +283,7 @@ static void automount_set_state(Automount *a, AutomountState state) {
         if (state != old_state)
                 log_unit_debug(UNIT(a), "Changed %s -> %s", automount_state_to_string(old_state), automount_state_to_string(state));
 
-        unit_notify(UNIT(a), state_translation_table[old_state], state_translation_table[state], 0);
+        unit_notify(UNIT(a), state_translation_table[old_state], state_translation_table[state], /* reload_success = */ true);
 }
 
 static int automount_coldplug(Unit *u) {
index 79082d1688b662dfe86af31aace2f57d80f0199e..60ab59c53b62178418de1df6f1bad52d85d9cb93 100644 (file)
@@ -182,7 +182,7 @@ static void device_set_state(Device *d, DeviceState state) {
         if (state != old_state)
                 log_unit_debug(UNIT(d), "Changed %s -> %s", device_state_to_string(old_state), device_state_to_string(state));
 
-        unit_notify(UNIT(d), state_translation_table[old_state], state_translation_table[state], 0);
+        unit_notify(UNIT(d), state_translation_table[old_state], state_translation_table[state], /* reload_success = */ true);
 }
 
 static void device_found_changed(Device *d, DeviceFound previous, DeviceFound now) {
index f25188681d78773eb3c969cdd29e2449b63394f9..8f02bd29d8a784a3cfb96a7e7b4c8385af34036a 100644 (file)
@@ -761,8 +761,7 @@ static void mount_set_state(Mount *m, MountState state) {
         if (state != old_state)
                 log_unit_debug(UNIT(m), "Changed %s -> %s", mount_state_to_string(old_state), mount_state_to_string(state));
 
-        unit_notify(UNIT(m), state_translation_table[old_state], state_translation_table[state],
-                    m->reload_result == MOUNT_SUCCESS ? 0 : UNIT_NOTIFY_RELOAD_FAILURE);
+        unit_notify(UNIT(m), state_translation_table[old_state], state_translation_table[state], m->reload_result == MOUNT_SUCCESS);
 }
 
 static int mount_coldplug(Unit *u) {
index c95663c3aaed76d20c27c7e9da56a83685922570..5fb14d9a10b4521ec796cfe965e238f69fce0e77 100644 (file)
@@ -477,7 +477,7 @@ static void path_set_state(Path *p, PathState state) {
         if (state != old_state)
                 log_unit_debug(UNIT(p), "Changed %s -> %s", path_state_to_string(old_state), path_state_to_string(state));
 
-        unit_notify(UNIT(p), state_translation_table[old_state], state_translation_table[state], 0);
+        unit_notify(UNIT(p), state_translation_table[old_state], state_translation_table[state], /* reload_success = */ true);
 }
 
 static void path_enter_waiting(Path *p, bool initial, bool from_trigger_notify);
index 5f3b62e02194f62da80f4d8986bc60bf4de26407..761eb5ea56e696eb730debd4dd395fad95037f3e 100644 (file)
@@ -127,7 +127,7 @@ static void scope_set_state(Scope *s, ScopeState state) {
         if (state != old_state)
                 log_debug("%s changed %s -> %s", UNIT(s)->id, scope_state_to_string(old_state), scope_state_to_string(state));
 
-        unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], 0);
+        unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], /* reload_success = */ true);
 }
 
 static int scope_add_default_dependencies(Scope *s) {
index 41e61987712f2c06ee0dbd390890de686870eb6e..533d7d3771a252b34bbebcef2f09c70442f9c5a8 100644 (file)
@@ -1277,9 +1277,7 @@ static void service_set_state(Service *s, ServiceState state) {
         if (old_state != state)
                 log_unit_debug(UNIT(s), "Changed %s -> %s", service_state_to_string(old_state), service_state_to_string(state));
 
-        unit_notify(UNIT(s), table[old_state], table[state],
-                    (s->reload_result == SERVICE_SUCCESS ? 0 : UNIT_NOTIFY_RELOAD_FAILURE) |
-                    (s->will_auto_restart ? UNIT_NOTIFY_WILL_AUTO_RESTART : 0));
+        unit_notify(UNIT(s), table[old_state], table[state], s->reload_result == SERVICE_SUCCESS);
 }
 
 static usec_t service_coldplug_timeout(Service *s) {
@@ -1946,8 +1944,6 @@ static bool service_will_restart(Unit *u) {
 
         assert(s);
 
-        if (s->will_auto_restart)
-                return true;
         if (IN_SET(s->state, SERVICE_DEAD_BEFORE_AUTO_RESTART, SERVICE_FAILED_BEFORE_AUTO_RESTART, SERVICE_AUTO_RESTART))
                 return true;
 
@@ -1993,19 +1989,14 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
                 log_unit_debug(UNIT(s), "Service restart not allowed.");
         else {
                 const char *reason;
-                bool shall_restart;
 
-                shall_restart = service_shall_restart(s, &reason);
+                allow_restart = service_shall_restart(s, &reason);
                 log_unit_debug(UNIT(s), "Service will %srestart (%s)",
-                                        shall_restart ? "" : "not ",
+                                        allow_restart ? "" : "not ",
                                         reason);
-                if (shall_restart)
-                        s->will_auto_restart = true;
         }
 
-        if (s->will_auto_restart) {
-                s->will_auto_restart = false;
-
+        if (allow_restart) {
                 /* We make two state changes here: one that maps to the high-level UNIT_INACTIVE/UNIT_FAILED
                  * state (i.e. a state indicating deactivation), and then one that that maps to the
                  * high-level UNIT_STARTING state (i.e. a state indicating activation). We do this so that
index 55c4127deed84b7dcc76b9d8e91065cabdc709fd..0e578c9280b841a9effdd971fe53cd1e467cda21 100644 (file)
@@ -181,8 +181,6 @@ struct Service {
         bool main_pid_alien:1;
         bool bus_name_good:1;
         bool forbid_restart:1;
-        /* Keep restart intention between UNIT_FAILED and UNIT_ACTIVATING */
-        bool will_auto_restart:1;
         bool start_timeout_defined:1;
         bool exec_fd_hot:1;
 
index c87b790a974c0dece1c761fa31a1e6a1b32959fb..490aabfd35ebe4ad3ede038030d1aafe53424256 100644 (file)
@@ -43,7 +43,7 @@ static void slice_set_state(Slice *t, SliceState state) {
                           slice_state_to_string(old_state),
                           slice_state_to_string(state));
 
-        unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], 0);
+        unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], /* reload_success = */ true);
 }
 
 static int slice_add_parent_slice(Slice *s) {
index 0bd1b126526c8a2d90ac3db92fa77bf72b95ffad..a6477de5a027d9a10d01e45de1e3056ba7ad6a27 100644 (file)
@@ -716,7 +716,7 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
                         prefix, strna(s->user),
                         prefix, strna(s->group));
 
-        if (s->keep_alive_time > 0)
+        if (timestamp_is_set(s->keep_alive_time))
                 fprintf(f,
                         "%sKeepAliveTimeSec: %s\n",
                         prefix, FORMAT_TIMESPAN(s->keep_alive_time, USEC_PER_SEC));
@@ -973,7 +973,7 @@ static void socket_apply_socket_options(Socket *s, SocketPort *p, int fd) {
                         log_unit_warning_errno(UNIT(s), r, "SO_KEEPALIVE failed: %m");
         }
 
-        if (s->keep_alive_time > 0) {
+        if (timestamp_is_set(s->keep_alive_time)) {
                 r = setsockopt_int(fd, SOL_TCP, TCP_KEEPIDLE, s->keep_alive_time / USEC_PER_SEC);
                 if (r < 0)
                         log_unit_warning_errno(UNIT(s), r, "TCP_KEEPIDLE failed: %m");
@@ -1844,7 +1844,7 @@ static void socket_set_state(Socket *s, SocketState state) {
         if (state != old_state)
                 log_unit_debug(UNIT(s), "Changed %s -> %s", socket_state_to_string(old_state), socket_state_to_string(state));
 
-        unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], 0);
+        unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], /* reload_success = */ true);
 }
 
 static int socket_coldplug(Unit *u) {
index 26a950b058d6fc56357b459bf4fbbbd90a67da8a..a57176b1a39f6d8ecc88c3a89bf0575ddd182f4b 100644 (file)
@@ -554,7 +554,7 @@ static void swap_set_state(Swap *s, SwapState state) {
         if (state != old_state)
                 log_unit_debug(UNIT(s), "Changed %s -> %s", swap_state_to_string(old_state), swap_state_to_string(state));
 
-        unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], 0);
+        unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], /* reload_success = */ true);
 
         /* If there other units for the same device node have a job
            queued it might be worth checking again if it is runnable
index 6225df5b0d4d8d3a5e3df748a0d992d556787b31..3519b4b653a05b1a4b6ca63bc42811e3c67ce083 100644 (file)
@@ -31,7 +31,7 @@ static void target_set_state(Target *t, TargetState state) {
                           target_state_to_string(old_state),
                           target_state_to_string(state));
 
-        unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], 0);
+        unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], /* reload_success = */ true);
 }
 
 static int target_add_default_dependencies(Target *t) {
index aab376e5cc775c03df20f01f1e424c60b9bdd941..f6e660550749814df23e167771335d9cf6ce5461 100644 (file)
@@ -298,7 +298,7 @@ static void timer_set_state(Timer *t, TimerState state) {
         if (state != old_state)
                 log_unit_debug(UNIT(t), "Changed %s -> %s", timer_state_to_string(old_state), timer_state_to_string(state));
 
-        unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], 0);
+        unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], /* reload_success = */ true);
 }
 
 static void timer_enter_waiting(Timer *t, bool time_change);
@@ -688,7 +688,7 @@ static int timer_serialize(Unit *u, FILE *f, FDSet *fds) {
         (void) serialize_item(f, "state", timer_state_to_string(t->state));
         (void) serialize_item(f, "result", timer_result_to_string(t->result));
 
-        if (t->last_trigger.realtime > 0)
+        if (dual_timestamp_is_set(&t->last_trigger))
                 (void) serialize_usec(f, "last-trigger-realtime", t->last_trigger.realtime);
 
         if (t->last_trigger.monotonic > 0)
index 3393138bac1fd5b3cecca92c6e677169b2a9968c..f7b8cf0abcd3452c7e86e75e3bc87d328179216b 100644 (file)
@@ -2111,7 +2111,7 @@ int unit_reload(Unit *u) {
 
         if (!UNIT_VTABLE(u)->reload) {
                 /* Unit doesn't have a reload function, but we need to propagate the reload anyway */
-                unit_notify(u, unit_active_state(u), unit_active_state(u), 0);
+                unit_notify(u, unit_active_state(u), unit_active_state(u), /* reload_success = */ true);
                 return 0;
         }
 
@@ -2622,7 +2622,7 @@ static void unit_emit_audit_stop(Unit *u, UnitActiveState state) {
         }
 }
 
-static bool unit_process_job(Job *j, UnitActiveState ns, UnitNotifyFlags flags) {
+static bool unit_process_job(Job *j, UnitActiveState ns, bool reload_success) {
         bool unexpected = false;
         JobResult result;
 
@@ -2664,7 +2664,7 @@ static bool unit_process_job(Job *j, UnitActiveState ns, UnitNotifyFlags flags)
 
                 if (j->state == JOB_RUNNING) {
                         if (ns == UNIT_ACTIVE)
-                                job_finish_and_invalidate(j, (flags & UNIT_NOTIFY_RELOAD_FAILURE) ? JOB_FAILED : JOB_DONE, true, false);
+                                job_finish_and_invalidate(j, reload_success ? JOB_DONE : JOB_FAILED, true, false);
                         else if (!IN_SET(ns, UNIT_ACTIVATING, UNIT_RELOADING)) {
                                 unexpected = true;
 
@@ -2695,7 +2695,7 @@ static bool unit_process_job(Job *j, UnitActiveState ns, UnitNotifyFlags flags)
         return unexpected;
 }
 
-void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlags flags) {
+void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_success) {
         const char *reason;
         Manager *m;
 
@@ -2760,7 +2760,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlag
 
                 /* Let's propagate state changes to the job */
                 if (u->job)
-                        unexpected = unit_process_job(u->job, ns, flags);
+                        unexpected = unit_process_job(u->job, ns, reload_success);
                 else
                         unexpected = true;
 
@@ -2777,9 +2777,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlag
 
                 if (ns != os && ns == UNIT_FAILED) {
                         log_unit_debug(u, "Unit entered failed state.");
-
-                        if (!(flags & UNIT_NOTIFY_WILL_AUTO_RESTART))
-                                unit_start_on_failure(u, "OnFailure=", UNIT_ATOM_ON_FAILURE, u->on_failure_job_mode);
+                        unit_start_on_failure(u, "OnFailure=", UNIT_ATOM_ON_FAILURE, u->on_failure_job_mode);
                 }
 
                 if (UNIT_IS_ACTIVE_OR_RELOADING(ns) && !UNIT_IS_ACTIVE_OR_RELOADING(os)) {
@@ -2796,8 +2794,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlag
                         unit_log_resources(u);
                 }
 
-                if (ns == UNIT_INACTIVE && !IN_SET(os, UNIT_FAILED, UNIT_INACTIVE, UNIT_MAINTENANCE) &&
-                    !(flags & UNIT_NOTIFY_WILL_AUTO_RESTART))
+                if (ns == UNIT_INACTIVE && !IN_SET(os, UNIT_FAILED, UNIT_INACTIVE, UNIT_MAINTENANCE))
                         unit_start_on_failure(u, "OnSuccess=", UNIT_ATOM_ON_SUCCESS, u->on_success_job_mode);
         }
 
index 7e85150643ec4c4418abcfa9870139d9d0295be2..09af8915dc35e33df5e33fca1938aabe6fc7ba45 100644 (file)
@@ -902,12 +902,7 @@ int unit_kill_common(Unit *u, KillWho who, int signo, int code, int value, pid_t
 
 void unit_notify_cgroup_oom(Unit *u, bool managed_oom);
 
-typedef enum UnitNotifyFlags {
-        UNIT_NOTIFY_RELOAD_FAILURE    = 1 << 0,
-        UNIT_NOTIFY_WILL_AUTO_RESTART = 1 << 1,
-} UnitNotifyFlags;
-
-void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlags flags);
+void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_success);
 
 int unit_watch_pid(Unit *u, pid_t pid, bool exclusive);
 void unit_unwatch_pid(Unit *u, pid_t pid);
index c6e201ecf20badcc432ab6489551bc2040ca5383..7e0c98cb7d45016c01c319d2320789287763d9ab 100644 (file)
@@ -187,8 +187,7 @@ int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) {
                                         if (!n)
                                                 return log_oom();
 
-                                        free(c->oldest_file);
-                                        c->oldest_file = n;
+                                        free_and_replace(c->oldest_file, n);
                                         c->oldest_mtime = t;
                                 }
 
index b9b310b6644aa2af2b51eb87a8d9e61ae3612840..fac90d22a21b1944fe18b3824ca4eebb7dd8238e 100644 (file)
@@ -271,8 +271,7 @@ int start_upload(Uploader *u,
                 /* truncate the potential old error message */
                 u->error[0] = '\0';
 
-                free(u->answer);
-                u->answer = 0;
+                u->answer = mfree(u->answer);
         }
 
         /* upload to this place */
index ca23508454fd1f9ea86dee9680c6644e943756b1..4888c38fdb012971d9c3a1ec5e7e14bb404e71e3 100644 (file)
@@ -66,20 +66,16 @@ static void server_process_entry_meta(
                 char *t;
 
                 t = memdup_suffix0(p + 18, l - 18);
-                if (t) {
-                        free(*identifier);
-                        *identifier = t;
-                }
+                if (t)
+                        free_and_replace(*identifier, t);
 
         } else if (l >= 8 &&
                    startswith(p, "MESSAGE=")) {
                 char *t;
 
                 t = memdup_suffix0(p + 8, l - 8);
-                if (t) {
-                        free(*message);
-                        *message = t;
-                }
+                if (t)
+                        free_and_replace(*message, t);
 
         } else if (l > STRLEN("OBJECT_PID=") &&
                    l < STRLEN("OBJECT_PID=")  + DECIMAL_STR_MAX(pid_t) &&
index 6672409d7533c3027f3af22123646c082e4faa71..af61c9b096bbace2e337408e28ba4601fd0178d7 100644 (file)
@@ -159,8 +159,7 @@ static int parse_string(sd_lldp_rx *lldp_rx, char **s, const void *q, size_t n)
         if (!k)
                 return log_oom_debug();
 
-        free(*s);
-        *s = k;
+        free_and_replace(*s, k);
 
         return 1;
 }
index 02c6a6e0d79133e90eb65c5c7dd65563e87bc981..b0a36324121835569471dd6cc35518d3ef92702a 100644 (file)
@@ -451,8 +451,7 @@ static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_add
                 if (!addresses)
                         return -ENOMEM;
 
-                free(*ret);
-                *ret = addresses;
+                free_and_replace(*ret, addresses);
                 *n_ret = n_addresses;
         }
 
@@ -795,8 +794,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
                         if (!p)
                                 return -ENOMEM;
 
-                        free(lease->vendor_specific);
-                        lease->vendor_specific = p;
+                        free_and_replace(lease->vendor_specific, p);
                 }
 
                 lease->vendor_specific_len = len;
@@ -1458,8 +1456,7 @@ int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const void *client_id, size_t
                 if (!p)
                         return -ENOMEM;
 
-                free(lease->client_id);
-                lease->client_id = p;
+                free_and_replace(lease->client_id, p);
                 lease->client_id_len = client_id_len;
         }
 
index 287cde6d419f61973952a4770e707ab1b7c4a5c0..77b4b5bea61ab3c65a7f06eaf8c028c6ada2177d 100644 (file)
@@ -590,10 +590,9 @@ _public_ int sd_bus_get_name_creds(
                                                 if (r < 0)
                                                         return r;
 
-                                                free(c->label);
-                                                c->label = strndup(p, sz);
-                                                if (!c->label)
-                                                        return -ENOMEM;
+                                                r = free_and_strndup(&c->label, p, sz);
+                                                if (r < 0)
+                                                        return r;
 
                                                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
 
index 741d54cabdfb624b33ff76199f8e61bd5a756140..e4e19972649a6c792ff6360b22714005c156835e 100644 (file)
@@ -337,8 +337,7 @@ static int bus_socket_auth_write(sd_bus *b, const char *t) {
         b->auth_iovec[0].iov_base = p;
         b->auth_iovec[0].iov_len += l;
 
-        free(b->auth_buffer);
-        b->auth_buffer = p;
+        free_and_replace(b->auth_buffer, p);
         b->auth_index = 0;
         return 0;
 }
@@ -868,8 +867,7 @@ static int bus_socket_inotify_setup(sd_bus *b) {
                         goto fail;
                 }
 
-                free(absolute);
-                absolute = c;
+                free_and_replace(absolute, c);
 
                 max_follow--;
         }
index a81b21062a733089429551f4a9bd5c85a0e0e37f..c5d54bbf74d238afd0c2b567a1ff98e4a7f781a7 100644 (file)
@@ -124,10 +124,9 @@ _public_ int sd_pid_get_cgroup(pid_t pid, char **cgroup) {
          * cgroup, let's return the "/" in the public APIs instead, as
          * that's easier and less ambiguous for people to grok. */
         if (isempty(c)) {
-                free(c);
-                c = strdup("/");
-                if (!c)
-                        return -ENOMEM;
+                r = free_and_strdup(&c, "/");
+                if (r < 0)
+                        return r;
 
         }
 
index 841b863024358e7cee22e6922fd78af04331aea3..dcd3547f8b90a2d63c4f3874e1d1302e967bde92 100644 (file)
@@ -1109,8 +1109,7 @@ static void resolve_freeaddrinfo(struct addrinfo *ai) {
 
                 free(ai->ai_addr);
                 free(ai->ai_canonname);
-                free(ai);
-                ai = next;
+                free_and_replace(ai, next);
         }
 }
 
index b1c4f1cad8e4dba8563e7abcf8f0838395ff120d..c2ba00c4381c69bafddfc764f679436fec470cbc 100644 (file)
@@ -712,10 +712,9 @@ int veth_extra_parse(char ***l, const char *p) {
         if (r < 0)
                 return r;
         if (r == 0 || !ifname_valid(b)) {
-                free(b);
-                b = strdup(a);
-                if (!b)
-                        return -ENOMEM;
+                r = free_and_strdup(&b, a);
+                if (r < 0)
+                        return r;
         }
 
         if (p)
index 86a6d3f6080971b1972c3ed7d622b4d137bc0981..78902dfbda68a7aa175069abf0f56ed4bd59dc94 100644 (file)
@@ -37,8 +37,7 @@ assert_cc(INT_MAX >= USEC_PER_SEC);
 static CalendarComponent* chain_free(CalendarComponent *c) {
         while (c) {
                 CalendarComponent *n = c->next;
-                free(c);
-                c = n;
+                free_and_replace(c, n);
         }
         return NULL;
 }
index ee5f8ec12ecf261cdfcc319429ec58603444149d..83b06902ab3046046d381474c4bb6c4ecfbacb1f 100644 (file)
 static const char *arg_dest = NULL;
 
 static int generate_symlink(void) {
-        _cleanup_free_ char *j = NULL;
-
         FOREACH_STRING(p, "/system-update", "/etc/system-update") {
-                if (laccess(p, F_OK) >= 0)
-                        goto link_found;
+                if (laccess(p, F_OK) >= 0) {
+                        _cleanup_free_ char *j = NULL;
+
+                        j = path_join(arg_dest, SPECIAL_DEFAULT_TARGET);
+                        if (!j)
+                                return log_oom();
+
+                        if (symlink(SYSTEM_DATA_UNIT_DIR "/system-update.target", j) < 0)
+                                return log_error_errno(errno, "Failed to create symlink %s: %m", j);
+
+                        return 1;
+                }
 
                 if (errno != ENOENT)
                         log_warning_errno(errno, "Failed to check if %s symlink exists, ignoring: %m", p);
         }
 
         return 0;
-
-link_found:
-        j = path_join(arg_dest, SPECIAL_DEFAULT_TARGET);
-        if (!j)
-                return log_oom();
-
-        if (symlink(SYSTEM_DATA_UNIT_DIR "/system-update.target", j) < 0)
-                return log_error_errno(errno, "Failed to create symlink %s: %m", j);
-
-        return 1;
 }
 
 static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
index d87670eb24aaa6e4c90ec6c3844656b830d85db8..60b2bf030be6d98a7dafa965d451320f3b350ad4 100755 (executable)
@@ -635,7 +635,7 @@ def make_uki(opts):
 
     if sign_kernel:
         linux_signed = tempfile.NamedTemporaryFile(prefix='linux-signed')
-        linux = linux_signed.name
+        linux = pathlib.Path(linux_signed.name)
         sign(sign_tool, opts.linux, linux, opts=opts)
     else:
         linux = opts.linux
index 4996272eb3a148033ea9c04ab5e107e01c7031b4..5651ec11dacf9900fcebef702020d91b7e7a3a06 100644 (file)
 #include "macro.h"
 #include "main-func.h"
 #include "process-util.h"
+#include "random-util.h"
 #include "special.h"
 #include "stdio-util.h"
 #include "strv.h"
 #include "unit-name.h"
 #include "utmp-wtmp.h"
+#include "verbs.h"
 
 typedef struct Context {
         sd_bus *bus;
@@ -44,20 +46,23 @@ static void context_clear(Context *c) {
 #endif
 }
 
-static usec_t get_startup_monotonic_time(Context *c) {
+static int get_startup_monotonic_time(Context *c, usec_t *ret) {
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-        usec_t t = 0;
         int r;
 
         assert(c);
+        assert(ret);
+
+        r = bus_get_property_trivial(
+                        c->bus,
+                        bus_systemd_mgr,
+                        "UserspaceTimestampMonotonic",
+                        &error,
+                        't', ret);
+        if (r < 0)
+                return log_warning_errno(r, "Failed to get timestamp, ignoring: %s", bus_error_message(&error, r));
 
-        r = bus_get_property_trivial(c->bus, bus_systemd_mgr, "UserspaceTimestampMonotonic", &error, 't', &t);
-        if (r < 0) {
-                log_error_errno(r, "Failed to get timestamp: %s", bus_error_message(&error, r));
-                return 0;
-        }
-
-        return t;
+        return 0;
 }
 
 static int get_current_runlevel(Context *c) {
@@ -65,116 +70,129 @@ static int get_current_runlevel(Context *c) {
                 const int runlevel;
                 const char *special;
         } table[] = {
-                /* The first target of this list that is active or has
-                 * a job scheduled wins. We prefer runlevels 5 and 3
-                 * here over the others, since these are the main
-                 * runlevels used on Fedora. It might make sense to
-                 * change the order on some distributions. */
+                /* The first target of this list that is active or has a job scheduled wins. We prefer
+                 * runlevels 5 and 3 here over the others, since these are the main runlevels used on Fedora.
+                 * It might make sense to change the order on some distributions. */
                 { '5', SPECIAL_GRAPHICAL_TARGET  },
                 { '3', SPECIAL_MULTI_USER_TARGET },
                 { '1', SPECIAL_RESCUE_TARGET     },
         };
-
-        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
         assert(c);
 
-        for (size_t i = 0; i < ELEMENTSOF(table); i++) {
-                _cleanup_free_ char *state = NULL, *path = NULL;
-
-                path = unit_dbus_path_from_name(table[i].special);
-                if (!path)
-                        return log_oom();
-
-                r = sd_bus_get_property_string(
-                                c->bus,
-                                "org.freedesktop.systemd1",
-                                path,
-                                "org.freedesktop.systemd1.Unit",
-                                "ActiveState",
-                                &error,
-                                &state);
-                if (r < 0)
-                        return log_warning_errno(r, "Failed to get state: %s", bus_error_message(&error, r));
+        for (unsigned n_attempts = 0;;) {
+                FOREACH_ARRAY(e, table, ELEMENTSOF(table)) {
+                        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+                        _cleanup_free_ char *state = NULL, *path = NULL;
+
+                        path = unit_dbus_path_from_name(e->special);
+                        if (!path)
+                                return log_oom();
+
+                        r = sd_bus_get_property_string(
+                                        c->bus,
+                                        "org.freedesktop.systemd1",
+                                        path,
+                                        "org.freedesktop.systemd1.Unit",
+                                        "ActiveState",
+                                        &error,
+                                        &state);
+                        if ((r == -ENOTCONN ||
+                             sd_bus_error_has_names(&error,
+                                                    SD_BUS_ERROR_NO_REPLY,
+                                                    SD_BUS_ERROR_DISCONNECTED)) &&
+                            ++n_attempts < 64) {
+
+                                /* systemd might have dropped off momentarily, let's not make this an error,
+                                 * and wait some random time. Let's pick a random time in the range 0ms…250ms,
+                                 * linearly scaled by the number of failed attempts. */
+
+                                usec_t usec = random_u64_range(UINT64_C(10) * USEC_PER_MSEC +
+                                                               UINT64_C(240) * USEC_PER_MSEC * n_attempts/64);
+                                log_debug_errno(r, "Failed to get state of %s, retrying after %s: %s",
+                                                e->special, FORMAT_TIMESPAN(usec, USEC_PER_MSEC), bus_error_message(&error, r));
+                                (void) usleep(usec);
+                                goto reconnect;
+                        }
+                        if (r < 0)
+                                return log_warning_errno(r, "Failed to get state of %s: %s", e->special, bus_error_message(&error, r));
+
+                        if (STR_IN_SET(state, "active", "reloading"))
+                                return e->runlevel;
+                }
 
-                if (STR_IN_SET(state, "active", "reloading"))
-                        return table[i].runlevel;
-        }
+                return 0;
 
-        return 0;
+reconnect:
+                c->bus = sd_bus_flush_close_unref(c->bus);
+                r = bus_connect_system_systemd(&c->bus);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to reconnect to system bus: %m");
+        }
 }
 
-static int on_reboot(Context *c) {
-        int r = 0, q;
-        usec_t t;
-        usec_t boottime;
+static int on_reboot(int argc, char *argv[], void *userdata) {
+        Context *c = ASSERT_PTR(userdata);
+        usec_t t = 0, boottime;
+        int r, q = 0;
 
-        assert(c);
-
-        /* We finished start-up, so let's write the utmp
-         * record and send the audit msg */
+        /* We finished start-up, so let's write the utmp record and send the audit msg. */
 
 #if HAVE_AUDIT
         if (c->audit_fd >= 0)
                 if (audit_log_user_comm_message(c->audit_fd, AUDIT_SYSTEM_BOOT, "", "systemd-update-utmp", NULL, NULL, NULL, 1) < 0 &&
                     errno != EPERM)
-                        r = log_error_errno(errno, "Failed to send audit message: %m");
+                        q = log_error_errno(errno, "Failed to send audit message: %m");
 #endif
 
-        /* If this call fails it will return 0, which
-         * utmp_put_reboot() will then fix to the current time */
-        t = get_startup_monotonic_time(c);
+        /* If this call fails, then utmp_put_reboot() will fix to the current time. */
+        (void) get_startup_monotonic_time(c, &t);
         boottime = map_clock_usec(t, CLOCK_MONOTONIC, CLOCK_REALTIME);
-        /* We query the recorded monotonic time here (instead of the system clock CLOCK_REALTIME),
-         * even though we actually want the system clock time. That's because there's a likely
-         * chance that the system clock wasn't set right during early boot. By manually converting
-         * the monotonic clock to the system clock here we can compensate
-         * for incorrectly set clocks during early boot. */
+        /* We query the recorded monotonic time here (instead of the system clock CLOCK_REALTIME), even
+         * though we actually want the system clock time. That's because there's a likely chance that the
+         * system clock wasn't set right during early boot. By manually converting the monotonic clock to the
+         * system clock here we can compensate for incorrectly set clocks during early boot. */
 
-        q = utmp_put_reboot(boottime);
-        if (q < 0)
-                r = log_error_errno(q, "Failed to write utmp record: %m");
+        r = utmp_put_reboot(boottime);
+        if (r < 0)
+                return log_error_errno(r, "Failed to write utmp record: %m");
 
-        return r;
+        return q;
 }
 
-static int on_shutdown(Context *c) {
-        int r = 0, q;
+static int on_shutdown(int argc, char *argv[], void *userdata) {
+        int r, q = 0;
 
-        assert(c);
-
-        /* We started shut-down, so let's write the utmp
-         * record and send the audit msg */
+        /* We started shut-down, so let's write the utmp record and send the audit msg. */
 
 #if HAVE_AUDIT
+        Context *c = ASSERT_PTR(userdata);
+
         if (c->audit_fd >= 0)
                 if (audit_log_user_comm_message(c->audit_fd, AUDIT_SYSTEM_SHUTDOWN, "", "systemd-update-utmp", NULL, NULL, NULL, 1) < 0 &&
                     errno != EPERM)
-                        r = log_error_errno(errno, "Failed to send audit message: %m");
+                        q = log_error_errno(errno, "Failed to send audit message: %m");
 #endif
 
-        q = utmp_put_shutdown();
-        if (q < 0)
-                r = log_error_errno(q, "Failed to write utmp record: %m");
+        r = utmp_put_shutdown();
+        if (r < 0)
+                return log_error_errno(r, "Failed to write utmp record: %m");
 
-        return r;
+        return q;
 }
 
-static int on_runlevel(Context *c) {
-        int r = 0, q, previous, runlevel;
+static int on_runlevel(int argc, char *argv[], void *userdata) {
+        Context *c = ASSERT_PTR(userdata);
+        int r, q = 0, previous, runlevel;
 
-        assert(c);
-
-        /* We finished changing runlevel, so let's write the
-         * utmp record and send the audit msg */
+        /* We finished changing runlevel, so let's write the utmp record and send the audit msg. */
 
         /* First, get last runlevel */
-        q = utmp_get_runlevel(&previous, NULL);
-
-        if (q < 0) {
-                if (!IN_SET(q, -ESRCH, -ENOENT))
-                        return log_error_errno(q, "Failed to get current runlevel: %m");
+        r = utmp_get_runlevel(&previous, NULL);
+        if (r < 0) {
+                if (!IN_SET(r, -ESRCH, -ENOENT))
+                        return log_error_errno(r, "Failed to get the last runlevel from utmp: %m");
 
                 previous = 0;
         }
@@ -184,7 +202,7 @@ static int on_runlevel(Context *c) {
         if (runlevel < 0)
                 return runlevel;
         if (runlevel == 0) {
-                log_warning("Failed to get new runlevel, utmp update skipped.");
+                log_warning("Failed to get the current runlevel, utmp update skipped.");
                 return 0;
         }
 
@@ -201,18 +219,25 @@ static int on_runlevel(Context *c) {
 
                 if (audit_log_user_comm_message(c->audit_fd, AUDIT_SYSTEM_RUNLEVEL, s,
                                                 "systemd-update-utmp", NULL, NULL, NULL, 1) < 0 && errno != EPERM)
-                        r = log_error_errno(errno, "Failed to send audit message: %m");
+                        q = log_error_errno(errno, "Failed to send audit message: %m");
         }
 #endif
 
-        q = utmp_put_runlevel(runlevel, previous);
-        if (q < 0 && !IN_SET(q, -ESRCH, -ENOENT))
-                return log_error_errno(q, "Failed to write utmp record: %m");
+        r = utmp_put_runlevel(runlevel, previous);
+        if (r < 0 && !IN_SET(r, -ESRCH, -ENOENT))
+                return log_error_errno(r, "Failed to write utmp record: %m");
 
-        return r;
+        return q;
 }
 
 static int run(int argc, char *argv[]) {
+        static const Verb verbs[] = {
+                { "reboot",   1, 1, 0, on_reboot   },
+                { "shutdown", 1, 1, 0, on_shutdown },
+                { "runlevel", 1, 1, 0, on_runlevel },
+                {}
+        };
+
         _cleanup_(context_clear) Context c = {
 #if HAVE_AUDIT
                 .audit_fd = -EBADF,
@@ -220,10 +245,6 @@ static int run(int argc, char *argv[]) {
         };
         int r;
 
-        if (argc != 2)
-                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                       "This program requires one argument.");
-
         log_setup();
 
         umask(0022);
@@ -232,20 +253,14 @@ static int run(int argc, char *argv[]) {
         /* If the kernel lacks netlink or audit support, don't worry about it. */
         c.audit_fd = audit_open();
         if (c.audit_fd < 0)
-                log_full_errno(IN_SET(errno, EAFNOSUPPORT, EPROTONOSUPPORT) ? LOG_DEBUG : LOG_ERR,
-                               errno, "Failed to connect to audit log: %m");
+                log_full_errno(IN_SET(errno, EAFNOSUPPORT, EPROTONOSUPPORT) ? LOG_DEBUG : LOG_WARNING,
+                               errno, "Failed to connect to audit log, ignoring: %m");
 #endif
         r = bus_connect_system_systemd(&c.bus);
         if (r < 0)
                 return log_error_errno(r, "Failed to get D-Bus connection: %m");
 
-        if (streq(argv[1], "reboot"))
-                return on_reboot(&c);
-        if (streq(argv[1], "shutdown"))
-                return on_shutdown(&c);
-        if (streq(argv[1], "runlevel"))
-                return on_runlevel(&c);
-        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown command %s", argv[1]);
+        return dispatch_verb(argc, argv, verbs, &c);
 }
 
 DEFINE_MAIN_FUNCTION(run);
index a55cc526a54edf69eebea85c95ffc7f9fafb5ea0..9074e0968f8931d9597b7629abaa88f582e48bf2 100644 (file)
@@ -1,10 +1,7 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 [Unit]
 Description=TEST-01-BASIC
-# Order the test unit after systemd-update-utmp-runlevel.service, since
-# the service doesn't play well with daemon-reexec
-# See: https://github.com/systemd/systemd/issues/27167
-After=multi-user.target systemd-update-utmp-runlevel.service
+After=multi-user.target
 Wants=systemd-resolved.service systemd-networkd.service
 
 [Service]
index 91dd47ca145717d2612746507b62376a7aab7a0f..475eaa2923df5195ec17f6ab76abeefcd611a079 100755 (executable)
@@ -44,4 +44,17 @@ systemctl daemon-reload
 # of systemd-analyze blame. See issue #27187.
 systemd-analyze blame
 
+# Test for 'systemd-update-utmp runlevel' vs 'systemctl daemon-reexec'.
+# See issue #27163.
+# shellcheck disable=SC2034
+for _ in {0..10}; do
+    systemctl daemon-reexec &
+    pid_reexec=$!
+    # shellcheck disable=SC2034
+    for _ in {0..10}; do
+        SYSTEMD_LOG_LEVEL=debug /usr/lib/systemd/systemd-update-utmp runlevel
+    done
+    wait "$pid_reexec"
+done
+
 echo OK >/testok