}
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");
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[]) {
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;