ev_run_list(&shutdown_event_list);
}
+static void
+child_event_hook(void *data UNUSED)
+{
+ log(L_INFO "Zombie elimination routine invoked.");
+ while (1) {
+ int status;
+ pid_t p = waitpid(-1, &status, WNOHANG);
+
+ if (p < 0)
+ {
+ log(L_ERR "Zombie elimination failed: %m");
+ return;
+ }
+
+ if (p == 0)
+ return;
+
+ const char *coreinfo = WCOREDUMP(status) ? " (core dumped)" : "";
+
+ if (WIFEXITED(status))
+ log(L_INFO "Process %d ended with status %d%s", p, WEXITSTATUS(status), coreinfo);
+ else if (WIFSIGNALED(status))
+ log(L_INFO "Process %d exited by signal %d (%s)%s", p, WTERMSIG(status), strsignal(WTERMSIG(status)), coreinfo);
+ else
+ log(L_ERR "Process %d exited with a strange status %d", p, status);
+ }
+}
+
event reboot_event = { .hook = reboot_event_hook },
- poweroff_event = { .hook = poweroff_event_hook };
+ poweroff_event = { .hook = poweroff_event_hook },
+ child_event = { .hook = child_event_hook };
callback shutdown_done_callback;
_exit(1);
}
+static void
+hypervisor_child_sighandler(int signo UNUSED)
+{
+ ev_send_loop(&main_birdloop, &child_event);
+}
/*
* The Main.
signal(SIGINT, hypervisor_poweroff_sighandler);
signal(SIGHUP, hypervisor_reboot_sighandler);
signal(SIGQUIT, hypervisor_fail_sighandler);
+ signal(SIGCHLD, hypervisor_child_sighandler);
/* Unblock signals */
sigprocmask(SIG_SETMASK, &oldmask, NULL);
}
/* Only one thing is actually supported for now: opening a listening socket */
- int sfd = socket(AF_INET6, SOCK_STREAM, 0);
+ int sfd = socket(AF_INET6, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (sfd < 0)
{
log(L_ERR "Failed to socket(): %m");
},
};
-
int e = bind(sfd, &sin.a, sizeof sin);
if (e < 0)
if (errno == EADDRINUSE)
}
static void
-hypervisor_exposed_child_err(sock *sk UNUSED, int e UNUSED)
+hypervisor_exposed_child_err(sock *sk, int e)
{
+ if (e == 0)
+ log(L_INFO "Exposed child exiting OK");
+ else
+ log(L_ERR "Exposed child control socket failure: %s", strerror(e));
+
+ sk_close(sk);
+ exit(!!e);
}
/**