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.
This commit is contained in:
Daan De Meyer 2023-12-17 19:41:56 +01:00
parent 68f74b0af2
commit c88753db45

View 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.");