All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] Improve -pidfile option
@ 2007-03-04  3:23 Anthony Liguori
  0 siblings, 0 replies; only message in thread
From: Anthony Liguori @ 2007-03-04  3:23 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 779 bytes --]

Howdy,

The following patch improves the -pidfile a fair bit.  -pidfile isn't 
terribly usable at the moment with -daemonize as the wrong pid gets 
written to the file.

Furthermore, there's a race in -pidfile between the stat() and initial 
create.  For a management tool, there's no 100% reliable way to know 
whether there's a stale pidfile or whether another QEMU process is running.

The attached patch uses a common technique for dealing with pidfiles.  
An advisory lock is taken once the pidfile is opened.  The nice thing 
about advisory locks is that the file is unlocked if a process dies.  
This allows for a truly atomic pidfile to be implemented.

AFAIK, lockf() exists on Windows.  I do not know if it works as one 
would expect though.

Regards,

Anthony Liguori

[-- Attachment #2: qemu-pidfile.diff --]
[-- Type: text/x-patch, Size: 2877 bytes --]

diff -r 58621c427a39 vl.c
--- a/vl.c	Sat Mar 03 21:06:59 2007 -0600
+++ b/vl.c	Sat Mar 03 21:15:21 2007 -0600
@@ -4387,44 +4387,24 @@ void usb_info(void)
     }
 }
 
-/***********************************************************/
-/* pid file */
-
-static char *pid_filename;
-
-/* Remove PID file. Called on normal exit */
-
-static void remove_pidfile(void) 
-{
-    unlink (pid_filename);
-}
-
-static void create_pidfile(const char *filename)
-{
-    struct stat pidstat;
-    FILE *f;
-
-    /* Try to write our PID to the named file */
-    if (stat(filename, &pidstat) < 0) {
-        if (errno == ENOENT) {
-            if ((f = fopen (filename, "w")) == NULL) {
-                perror("Opening pidfile");
-                exit(1);
-            }
-            fprintf(f, "%d\n", getpid());
-            fclose(f);
-            pid_filename = qemu_strdup(filename);
-            if (!pid_filename) {
-                fprintf(stderr, "Could not save PID filename");
-                exit(1);
-            }
-            atexit(remove_pidfile);
-        }
-    } else {
-        fprintf(stderr, "%s already exists. Remove it and try again.\n", 
-                filename);
-        exit(1);
-    }
+static int create_pidfile(const char *filename)
+{
+    int fd;
+    char buffer[128];
+    int len;
+
+    fd = open(filename, O_RDWR | O_CREAT, 0600);
+    if (fd == -1)
+	return -1;
+
+    if (lockf(fd, F_TLOCK, 0) == -1)
+	return -1;
+
+    len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid());
+    if (write(fd, buffer, len) != len)
+	return -1;
+
+    return 0;
 }
 
 /***********************************************************/
@@ -6874,6 +6854,7 @@ int main(int argc, char **argv)
     char usb_devices[MAX_USB_CMDLINE][128];
     int usb_devices_index;
     int fds[2];
+    const char *pid_file = NULL;
 
     LIST_INIT (&vm_change_state_head);
 #ifndef _WIN32
@@ -7263,7 +7244,7 @@ int main(int argc, char **argv)
                 break;
 #endif
             case QEMU_OPTION_pidfile:
-                create_pidfile(optarg);
+		pid_file = optarg;
                 break;
 #ifdef TARGET_I386
             case QEMU_OPTION_win2k_hack:
@@ -7353,9 +7334,12 @@ int main(int argc, char **argv)
 	    if (len == -1 && (errno == EINTR))
 		goto again;
 	    
-	    if (len != 1 || status != 0)
+	    if (len != 1)
 		exit(1);
-	    else
+	    else if (status == 1) {
+		fprintf(stderr, "Could not acquire pidfile\n");
+		exit(1);
+	    } else
 		exit(0);
 	} else if (pid < 0)
 	    exit(1);
@@ -7376,6 +7360,15 @@ int main(int argc, char **argv)
         signal(SIGTTIN, SIG_IGN);
     }
 #endif
+
+    if (pid_file && create_pidfile(pid_file) != 0) {
+	if (daemonize) {
+	    uint8_t status = 1;
+	    write(fds[1], &status, 1);
+	} else
+	    fprintf(stderr, "Could not acquire pid file\n");
+	exit(1);
+    }
 
 #ifdef USE_KQEMU
     if (smp_cpus > 1)

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2007-03-04  3:23 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-03-04  3:23 [Qemu-devel] [PATCH] Improve -pidfile option Anthony Liguori

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.