[libvirt] [PATCH 5/5] Convert libvirtd to use crash-safe pidfile APIs

Daniel P. Berrange berrange at redhat.com
Wed Aug 10 15:37:28 UTC 2011


From: "Daniel P. Berrange" <berrange at redhat.com>

Remove the current libvirtd pidfile handling code, in favour of
calling out to the new APIs. This ensures libvirtd's pidfile
handling is crashsafe

This also means that the non-root libvirtd instances (for handling
qemu:///session URIs) can now safely use pidfiles without racing

* daemon/libvirtd.c: Switch to use virPidFileAcquire and
  virPidFileRelease
---
 daemon/libvirtd.c |   60 +++++++++-------------------------------------------
 1 files changed, 11 insertions(+), 49 deletions(-)

diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index 53f1002..b866a01 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -35,6 +35,7 @@
 #include "libvirt_internal.h"
 #include "virterror_internal.h"
 #include "virfile.h"
+#include "virpidfile.h"
 
 #define VIR_FROM_THIS VIR_FROM_QEMU
 
@@ -259,44 +260,6 @@ static int daemonForkIntoBackground(const char *argv0)
     }
 }
 
-static int daemonWritePidFile(const char *pidFile, const char *argv0)
-{
-    int fd;
-    FILE *fh;
-    char ebuf[1024];
-
-    if (pidFile[0] == '\0')
-        return 0;
-
-    if ((fd = open(pidFile, O_WRONLY|O_CREAT|O_EXCL, 0644)) < 0) {
-        VIR_ERROR(_("Failed to open pid file '%s' : %s"),
-                  pidFile, virStrerror(errno, ebuf, sizeof ebuf));
-        return -1;
-    }
-
-    if (!(fh = VIR_FDOPEN(fd, "w"))) {
-        VIR_ERROR(_("Failed to fdopen pid file '%s' : %s"),
-                  pidFile, virStrerror(errno, ebuf, sizeof ebuf));
-        VIR_FORCE_CLOSE(fd);
-        return -1;
-    }
-
-    if (fprintf(fh, "%lu\n", (unsigned long)getpid()) < 0) {
-        VIR_ERROR(_("%s: Failed to write to pid file '%s' : %s"),
-                  argv0, pidFile, virStrerror(errno, ebuf, sizeof ebuf));
-        VIR_FORCE_FCLOSE(fh);
-        return -1;
-    }
-
-    if (VIR_FCLOSE(fh) == EOF) {
-        VIR_ERROR(_("%s: Failed to close pid file '%s' : %s"),
-                  argv0, pidFile, virStrerror(errno, ebuf, sizeof ebuf));
-        return -1;
-    }
-
-    return 0;
-}
-
 
 static int
 daemonPidFilePath(bool privileged,
@@ -1261,6 +1224,7 @@ int main(int argc, char **argv) {
     char *remote_config_file = NULL;
     int statuswrite = -1;
     int ret = 1;
+    int pid_file_fd = -1;
     char *pid_file = NULL;
     char *sock_file = NULL;
     char *sock_file_ro = NULL;
@@ -1378,7 +1342,7 @@ int main(int argc, char **argv) {
     if (daemonSetupLogging(config, privileged, verbose, godaemon) < 0)
         exit(EXIT_FAILURE);
 
-    if (!pid_file && privileged &&
+    if (!pid_file &&
         daemonPidFilePath(privileged,
                           &pid_file) < 0)
         exit(EXIT_FAILURE);
@@ -1405,14 +1369,6 @@ int main(int argc, char **argv) {
         }
     }
 
-    /* If we have a pidfile set, claim it now, exiting if already taken */
-    if (pid_file != NULL &&
-        daemonWritePidFile(pid_file, argv[0]) < 0) {
-        VIR_FREE(pid_file); /* Prevent unlinking of someone else's pid ! */
-        ret = VIR_DAEMON_ERR_PIDFILE;
-        goto cleanup;
-    }
-
     /* Ensure the rundir exists (on tmpfs on some systems) */
     if (privileged) {
         const char *rundir = LOCALSTATEDIR "/run/libvirt";
@@ -1432,6 +1388,12 @@ int main(int argc, char **argv) {
         umask(old_umask);
     }
 
+    /* Try to claim the pidfile, exiting if we can't */
+    if ((pid_file_fd = virPidFileAcquirePath(pid_file, getpid())) < 0) {
+        ret = VIR_DAEMON_ERR_PIDFILE;
+        goto cleanup;
+    }
+
     use_polkit_dbus = config->auth_unix_rw == REMOTE_AUTH_POLKIT ||
             config->auth_unix_ro == REMOTE_AUTH_POLKIT;
     if (!(srv = virNetServerNew(config->min_workers,
@@ -1570,8 +1532,8 @@ cleanup:
         }
         VIR_FORCE_CLOSE(statuswrite);
     }
-    if (pid_file)
-        unlink (pid_file);
+    if (pid_file_fd != -1)
+        virPidFileReleasePath(pid_file, pid_file_fd);
 
     VIR_FREE(sock_file);
     VIR_FREE(sock_file_ro);
-- 
1.7.6




More information about the libvir-list mailing list