Skip to content

Commit 74e07b3

Browse files
committed
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.
1 parent 24f2ff1 commit 74e07b3

File tree

2 files changed

+14
-9
lines changed

2 files changed

+14
-9
lines changed

src/libsystemd/sd-daemon/sd-daemon.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,16 @@ static int pid_notify_with_fds_internal(
513513
}
514514

515515
if (address.sockaddr.sa.sa_family == AF_VSOCK) {
516+
/* If we shut down a virtual machine the kernel might not flush the buffers of the vsock
517+
* socket before shutting down. Set SO_LINGER so that we wait until the buffers are flushed
518+
* when the socket is closed. */
519+
struct linger l = {
520+
.l_onoff = true,
521+
.l_linger = 10,
522+
};
523+
if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) < 0)
524+
log_debug_errno(errno, "Failed to set SO_LINGER on vsock notify socket, ignoring: %m");
525+
516526
r = vsock_bind_privileged_port(fd);
517527
if (r < 0 && !ERRNO_IS_PRIVILEGE(r))
518528
return log_debug_errno(r, "Failed to bind socket to privileged port: %m");

src/shutdown/shutdown.c

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -344,13 +344,15 @@ static void notify_supervisor(void) {
344344

345345
if (reboot_parameter)
346346
(void) sd_notifyf(/* unset_environment= */ false,
347+
"EXIT_STATUS=%i\n"
347348
"X_SYSTEMD_SHUTDOWN=%s\n"
348349
"X_SYSTEMD_REBOOT_PARAMETER=%s",
349-
arg_verb, reboot_parameter);
350+
arg_exit_code, arg_verb, reboot_parameter);
350351
else
351352
(void) sd_notifyf(/* unset_environment= */ false,
353+
"EXIT_STATUS=%i\n"
352354
"X_SYSTEMD_SHUTDOWN=%s",
353-
arg_verb);
355+
arg_exit_code, arg_verb);
354356
}
355357

356358
int main(int argc, char *argv[]) {
@@ -407,13 +409,6 @@ int main(int argc, char *argv[]) {
407409
goto error;
408410
}
409411

410-
/* This is primarily useful when running systemd in a VM, as it provides the user running the VM with
411-
* a mechanism to pick up systemd's exit status in the VM. Note that we execute this as early as
412-
* possible since otherwise we might shut down the VM before the AF_VSOCK buffers have been flushed.
413-
* While this doesn't guarantee the message will arrive, in practice we do enough work after this
414-
* that the message should always arrive on the host */
415-
(void) sd_notifyf(0, "EXIT_STATUS=%i", arg_exit_code);
416-
417412
(void) cg_get_root_path(&cgroup);
418413
bool in_container = detect_container() > 0;
419414

0 commit comments

Comments
 (0)