From c88753db45082c95ffd005e7a9e789f328989d46 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Sun, 17 Dec 2023 19:41:56 +0100 Subject: [PATCH] shutdown: Send EXIT_STATUS before final sync 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 | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/shutdown/shutdown.c b/src/shutdown/shutdown.c index b976b7d8cf6..b709078afed 100644 --- a/src/shutdown/shutdown.c +++ b/src/shutdown/shutdown.c @@ -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."); -- 2.39.5