Skip to content
Snippets Groups Projects
Commit 43b7dacb authored by Laurent Léonard's avatar Laurent Léonard
Browse files

Don't let parent of daemon exit until basic initialization is done.

parent 35451bf3
No related branches found
No related tags found
No related merge requests found
From: =?utf-8?q?Laurent=20L=C3=A9onard?= <laurent@open-minds.org>
Date: Sun, 25 Oct 2009 01:36:36 +0200
Subject: [PATCH] Don't let parent of daemon exit until basic initialization is done.
---
daemon/libvirtd.c | 116 +++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 99 insertions(+), 17 deletions(-)
diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index 78dfb2d..d102c66 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -185,6 +185,30 @@ static int max_client_requests = 5;
static sig_atomic_t sig_errors = 0;
static int sig_lasterrno = 0;
+enum {
+ VIR_DAEMON_ERR_NONE = 0,
+ VIR_DAEMON_ERR_PIDFILE,
+ VIR_DAEMON_ERR_RUNDIR,
+ VIR_DAEMON_ERR_INIT,
+ VIR_DAEMON_ERR_SIGNAL,
+ VIR_DAEMON_ERR_PRIVS,
+ VIR_DAEMON_ERR_NETWORK,
+ VIR_DAEMON_ERR_CONFIG,
+
+ VIR_DAEMON_ERR_LAST
+};
+
+VIR_ENUM_DECL(virDaemonErr)
+VIR_ENUM_IMPL(virDaemonErr, VIR_DAEMON_ERR_LAST,
+ "Initialization successful",
+ "Unable to obtain pidfile",
+ "Unable to create rundir",
+ "Unable to initialize libvirt",
+ "Unable to setup signal handlers",
+ "Unable to drop privileges",
+ "Unable to initialize network sockets",
+ "Unable to load configuration file")
+
static void sig_handler(int sig, siginfo_t * siginfo,
void* context ATTRIBUTE_UNUSED) {
int origerrno;
@@ -375,7 +399,11 @@ qemudDispatchSignalEvent(int watch ATTRIBUTE_UNUSED,
}
-static int qemudGoDaemon(void) {
+static int daemonForkIntoBackground(void) {
+ int statuspipe[2];
+ if (pipe(statuspipe) < 0)
+ return -1;
+
int pid = fork();
switch (pid) {
case 0:
@@ -384,6 +412,8 @@ static int qemudGoDaemon(void) {
int stdoutfd = -1;
int nextpid;
+ close(statuspipe[0]);
+
if ((stdinfd = open("/dev/null", O_RDONLY)) < 0)
goto cleanup;
if ((stdoutfd = open("/dev/null", O_WRONLY)) < 0)
@@ -407,7 +437,7 @@ static int qemudGoDaemon(void) {
nextpid = fork();
switch (nextpid) {
case 0:
- return 0;
+ return statuspipe[1];
case -1:
return -1;
default:
@@ -428,15 +458,29 @@ static int qemudGoDaemon(void) {
default:
{
- int got, status = 0;
- /* We wait to make sure the next child forked
- successfully */
- if ((got = waitpid(pid, &status, 0)) < 0 ||
+ int got, exitstatus = 0;
+ int ret;
+ char status;
+
+ close(statuspipe[1]);
+
+ /* We wait to make sure the first child forked successfully */
+ if ((got = waitpid(pid, &exitstatus, 0)) < 0 ||
got != pid ||
status != 0) {
return -1;
}
- _exit(0);
+
+ /* Now block until the second child initializes successfully */
+ again:
+ ret = read(statuspipe[0], &status, 1);
+ if (ret == -1 && errno == EINTR)
+ goto again;
+
+ if (ret == 1 && status != 0) {
+ fprintf(stderr, "error: %s\n", virDaemonErrTypeToString(status));
+ }
+ _exit(ret == 1 && status == 0 ? 0 : 1);
}
}
}
@@ -859,8 +903,6 @@ static struct qemud_server *qemudInitialize(int sigread) {
virEventUpdateTimeoutImpl,
virEventRemoveTimeoutImpl);
- virStateInitialize(server->privileged);
-
return server;
}
@@ -2842,6 +2884,7 @@ int main(int argc, char **argv) {
int sigpipe[2];
const char *pid_file = NULL;
const char *remote_config_file = NULL;
+ int statuswrite = -1;
int ret = 1;
struct option opts[] = {
@@ -2923,7 +2966,7 @@ int main(int argc, char **argv) {
if (godaemon) {
char ebuf[1024];
- if (qemudGoDaemon() < 0) {
+ if ((statuswrite = daemonForkIntoBackground()) < 0) {
VIR_ERROR(_("Failed to fork as daemon: %s"),
virStrerror(errno, ebuf, sizeof ebuf));
goto error1;
@@ -2938,8 +2981,11 @@ int main(int argc, char **argv) {
/* If we have a pidfile set, claim it now, exiting if already taken */
if (pid_file != NULL &&
- qemudWritePidFile (pid_file) < 0)
+ qemudWritePidFile (pid_file) < 0) {
+ pid_file = NULL; /* Prevent unlinking of someone else's pid ! */
+ ret = VIR_DAEMON_ERR_PIDFILE;
goto error1;
+ }
if (pipe(sigpipe) < 0 ||
virSetNonBlock(sigpipe[0]) < 0 ||
@@ -2973,7 +3019,8 @@ int main(int argc, char **argv) {
if (mkdir (rundir, 0755)) {
if (errno != EEXIST) {
VIR_ERROR0 (_("unable to create rundir"));
- return -1;
+ ret = VIR_DAEMON_ERR_RUNDIR;
+ goto error1;
}
}
}
@@ -2984,17 +3031,21 @@ int main(int argc, char **argv) {
* which is also passed into all libvirt stateful
* drivers
*/
- if (qemudSetupPrivs() < 0)
+ if (qemudSetupPrivs() < 0) {
+ ret = VIR_DAEMON_ERR_PRIVS;
goto error2;
+ }
if (!(server = qemudInitialize(sigpipe[0]))) {
- ret = 2;
+ ret = VIR_DAEMON_ERR_INIT;
goto error2;
}
/* Read the config file (if it exists). */
- if (remoteReadConfigFile (server, remote_config_file) < 0)
+ if (remoteReadConfigFile (server, remote_config_file) < 0) {
+ ret = VIR_DAEMON_ERR_CONFIG;
goto error2;
+ }
/* Change the group ownership of /var/run/libvirt to unix_sock_gid */
if (unix_sock_dir && server->privileged) {
@@ -3013,15 +3064,46 @@ int main(int argc, char **argv) {
}
if (!(server = qemudNetworkInit(server))) {
- ret = 2;
+ ret = VIR_DAEMON_ERR_NETWORK;
goto error2;
}
- qemudRunLoop(server);
+ /* Tell parent of daemon that basic initialization is complete
+ * In particular we're ready to accept net connections & have
+ * written the pidfile
+ */
+ if (statuswrite != -1) {
+ char status = 0;
+ while (write(statuswrite, &status, 1) == -1 &&
+ errno == EINTR)
+ ;
+ close(statuswrite);
+ statuswrite = -1;
+ }
+
+ /* Start the stateful HV drivers
+ * This is delibrately done after telling the parent process
+ * we're ready, since it can take a long time and this will
+ * seriously delay OS bootup process */
+ if (virStateInitialize(server->privileged) < 0) {
+ VIR_ERROR0("Driver state initialization failed");
+ goto error2;
+ }
+ qemudRunLoop(server);
ret = 0;
error2:
+ if (statuswrite != -1) {
+ if (ret != 0) {
+ /* Tell parent of daemon what failed */
+ char status = ret;
+ while (write(statuswrite, &status, 1) == -1 &&
+ errno == EINTR)
+ ;
+ }
+ close(statuswrite);
+ }
if (server)
qemudCleanup(server);
if (pid_file)
--
......@@ -3,3 +3,4 @@
0003-allow-libvirt-group-to-access-the-socket.patch
0004-fix-Debian-specific-path-to-hvm-loader.patch
0005-Fix-SELinux-linking-issues.patch
0006-Don-t-let-parent-of-daemon-exit-until-basic-initiali.patch
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment