From: "Daniel P. Berrange" <berrange(a)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