[libvirt] [PATCH 3/3] Speed up waiting for the session daemon

Martin Kletzander mkletzan at redhat.com
Thu Apr 18 10:30:56 UTC 2013


Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=927369

When launching the session daemon, we were waiting for around 20
seconds even it died before creating any sockets etc.

The following modification pre-creates the pidfile which will be used
by the forked daemon and cleans it up in case the daemon doesn't start
successfully.  This makes it possible to check whether the daemon
started and died immediately.

The pidfile is needed due to the process being daemonized.  Neither
creation nor locking the pidfile will fail in the daemon thanks to the
same PID keeping the lock.

Signed-off-by: Martin Kletzander <mkletzan at redhat.com>
---
 src/rpc/virnetsocket.c | 41 +++++++++++++++++++++++++++++++++++------
 1 file changed, 35 insertions(+), 6 deletions(-)

diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c
index c4fd9ee..835e11f 100644
--- a/src/rpc/virnetsocket.c
+++ b/src/rpc/virnetsocket.c
@@ -52,6 +52,7 @@
 #include "virfile.h"
 #include "virthread.h"
 #include "virprocess.h"
+#include "virpidfile.h"

 #include "passfd.h"

@@ -119,20 +120,29 @@ VIR_ONCE_GLOBAL_INIT(virNetSocket)


 #ifndef WIN32
-static int virNetSocketForkDaemon(const char *binary)
+static int virNetSocketForkDaemon(const char *binary, char **pidfile)
 {
-    int ret;
+    int ret = -1;
     virCommandPtr cmd = virCommandNewArgList(binary,
                                              "--timeout=30",
                                              NULL);

+    if (pidfile &&
+        virGetDaemonPidFilePath(false, pidfile) < 0) {
+        goto cleanup;
+    }
+
     virCommandAddEnvPassCommon(cmd);
     virCommandAddEnvPass(cmd, "XDG_CACHE_HOME");
     virCommandAddEnvPass(cmd, "XDG_CONFIG_HOME");
     virCommandAddEnvPass(cmd, "XDG_RUNTIME_DIR");
     virCommandClearCaps(cmd);
     virCommandDaemonize(cmd);
+    if (pidfile)
+        virCommandSetPidFile(cmd, *pidfile);
     ret = virCommandRun(cmd, NULL);
+
+ cleanup:
     virCommandFree(cmd);
     return ret;
 }
@@ -523,6 +533,9 @@ int virNetSocketNewConnectUNIX(const char *path,
     virSocketAddr remoteAddr;
     int fd;
     int retries = 0;
+    char *pidfile = NULL;
+    pid_t pid;
+    int ret = -1;

     memset(&localAddr, 0, sizeof(localAddr));
     memset(&remoteAddr, 0, sizeof(remoteAddr));
@@ -556,8 +569,24 @@ retry:
             VIR_DEBUG("Connection refused for %s, trying to spawn %s",
                       path, binary);
             if (retries == 0 &&
-                virNetSocketForkDaemon(binary) < 0)
+                virNetSocketForkDaemon(binary, &pidfile) < 0)
+                goto error;
+
+            ret = virPidFileReadPathIfAlive(pidfile, &pid, binary);
+            if (ret < 0) {
+                virReportSystemError(-ret,
+                                     _("Cannot read pidfile '%s'"),
+                                     pidfile);
                 goto error;
+            }
+            ret = -1;
+
+            if (pid == -1) {
+                virPidFileDeletePath(pidfile);
+                virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
+                               _("Spawned binary died prematurely"));
+                goto error;
+            }

             retries++;
             usleep(1000 * 100 * retries);
@@ -579,11 +608,11 @@ retry:
     if (!(*retsock = virNetSocketNew(&localAddr, &remoteAddr, true, fd, -1, 0)))
         goto error;

-    return 0;
-
+    ret = 0;
 error:
+    VIR_FREE(pidfile);
     VIR_FORCE_CLOSE(fd);
-    return -1;
+    return ret;
 }
 #else
 int virNetSocketNewConnectUNIX(const char *path ATTRIBUTE_UNUSED,
-- 
1.8.1.5




More information about the libvir-list mailing list