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
This commit is contained in:
Daniel P. Berrange 2011-08-05 15:11:11 +01:00
parent e1da464d88
commit c8a3a26513

View File

@ -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);