diff options
author | Daan De Meyer <daan.j.demeyer@gmail.com> | 2024-04-25 19:35:07 +0200 |
---|---|---|
committer | Daan De Meyer <daan.j.demeyer@gmail.com> | 2024-04-25 21:29:34 +0200 |
commit | 74e07b33b05f6a7a7124f6e3a27fcd228837264e (patch) | |
tree | f0e5fa8a5e7b744cf52d11e401e246d734830c19 | |
parent | Merge pull request #32484 from DaanDeMeyer/mkosi-ci (diff) | |
download | systemd-74e07b33b05f6a7a7124f6e3a27fcd228837264e.tar.xz systemd-74e07b33b05f6a7a7124f6e3a27fcd228837264e.zip |
sd-daemon: Set SO_LINGER on AF_VSOCK notify socket fds
We're still seeing problems in mkosi CI where we lose notify messages
sent over vsock from virtual machines because the virtual machine shuts
down before the socket buffers are flushed.
Let's try setting SO_LINGER on vsock sockets so that the kernel waits
until the buffers are flushed when we close the file descriptor.
To make sure it works, let's get rid of our previous workaround that
sends EXIT_STATUS earlier to reduce the chance of it not arriving.
This way, if it doesn't work, we'll notice it immediately due to CI
failures.
-rw-r--r-- | src/libsystemd/sd-daemon/sd-daemon.c | 10 | ||||
-rw-r--r-- | src/shutdown/shutdown.c | 13 |
2 files changed, 14 insertions, 9 deletions
diff --git a/src/libsystemd/sd-daemon/sd-daemon.c b/src/libsystemd/sd-daemon/sd-daemon.c index 2ff9537a6d..20065a6a36 100644 --- a/src/libsystemd/sd-daemon/sd-daemon.c +++ b/src/libsystemd/sd-daemon/sd-daemon.c @@ -513,6 +513,16 @@ static int pid_notify_with_fds_internal( } if (address.sockaddr.sa.sa_family == AF_VSOCK) { + /* If we shut down a virtual machine the kernel might not flush the buffers of the vsock + * socket before shutting down. Set SO_LINGER so that we wait until the buffers are flushed + * when the socket is closed. */ + struct linger l = { + .l_onoff = true, + .l_linger = 10, + }; + if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) < 0) + log_debug_errno(errno, "Failed to set SO_LINGER on vsock notify socket, ignoring: %m"); + r = vsock_bind_privileged_port(fd); if (r < 0 && !ERRNO_IS_PRIVILEGE(r)) return log_debug_errno(r, "Failed to bind socket to privileged port: %m"); diff --git a/src/shutdown/shutdown.c b/src/shutdown/shutdown.c index 1ddda00941..67f44e16e9 100644 --- a/src/shutdown/shutdown.c +++ b/src/shutdown/shutdown.c @@ -344,13 +344,15 @@ static void notify_supervisor(void) { if (reboot_parameter) (void) sd_notifyf(/* unset_environment= */ false, + "EXIT_STATUS=%i\n" "X_SYSTEMD_SHUTDOWN=%s\n" "X_SYSTEMD_REBOOT_PARAMETER=%s", - arg_verb, reboot_parameter); + arg_exit_code, arg_verb, reboot_parameter); else (void) sd_notifyf(/* unset_environment= */ false, + "EXIT_STATUS=%i\n" "X_SYSTEMD_SHUTDOWN=%s", - arg_verb); + arg_exit_code, arg_verb); } int main(int argc, char *argv[]) { @@ -407,13 +409,6 @@ 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; |