]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
shutdown: Send EXIT_STATUS before final sync
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Sun, 17 Dec 2023 18:41:56 +0000 (19:41 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 18 Dec 2023 12:21:17 +0000 (13:21 +0100)
There's a race condition where the EXIT_STATUS= message we send
just before shutting down the VM doesn't arrive on the host,
presumably because the VM is shut down before the kernel has had a
chance to forward the message to the host.

Since there's no obvious way to wait until the message has been
flushed to the host, let's send the message before we execute the
final sync() instead of after executing the final sync(). In my
testing, this seems to either guarantee the message is sent or
introduces sufficient delay that the kernel always has time to flush
its socket buffers to the host.

src/shutdown/shutdown.c

index b976b7d8cf60d299cc96d4a8192dddfc62003f34..b709078afed190056bb3b47951d87a4cb415ef08 100644 (file)
@@ -387,6 +387,13 @@ int main(int argc, char *argv[]) {
                 goto error;
         }
 
+        /* This is primarily useful when running systemd in a VM, as it provides the user running the VM with
+         * a mechanism to pick up systemd's exit status in the VM. Note that we execute this as early as
+         * possible since otherwise we might shut down the VM before the AF_VSOCK buffers have been flushed.
+         * While this doesn't guarantee the message will arrive, in practice we do enough work after this
+         * that the message should always arrive on the host */
+        (void) sd_notifyf(0, "EXIT_STATUS=%i", arg_exit_code);
+
         (void) cg_get_root_path(&cgroup);
         bool in_container = detect_container() > 0;
 
@@ -582,10 +589,6 @@ int main(int argc, char *argv[]) {
         if (!in_container)
                 sync_with_progress();
 
-        /* This is primarily useful when running systemd in a VM, as it provides the user running the VM with
-         * a mechanism to pick up systemd's exit status in the VM. */
-        (void) sd_notifyf(0, "EXIT_STATUS=%i", arg_exit_code);
-
         if (streq(arg_verb, "exit")) {
                 if (in_container) {
                         log_info("Exiting container.");