From c8a3a265135a0527b46aeb0ebd39de8a03189fb0 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Fri, 5 Aug 2011 15:11:11 +0100 Subject: [PATCH] Convert libvirtd to use crash-safe pidfile APIs 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 file changed, 11 insertions(+), 49 deletions(-) diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index 53f1002b87..b866a015b0 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); -- 2.39.5