* PID and lock file fixes
authorLennart Poettering <lennart@poettering.net>
Sun, 21 Nov 2004 13:18:56 +0000 (13:18 +0000)
committerLennart Poettering <lennart@poettering.net>
Sun, 21 Nov 2004 13:18:56 +0000 (13:18 +0000)
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@299 fefdeb5f-60dc-0310-8127-8f9354f1896f

polyp/pid.c
polyp/util.c

index 37a7698..232de21 100644 (file)
@@ -65,9 +65,62 @@ static pid_t read_pid(const char *fn, int fd) {
     return (pid_t) pid;
 }
 
+static int open_pid_file(const char *fn, int mode) {
+    int fd = -1;
+    int lock = -1;
+    
+    for (;;) {
+        struct stat st;
+        
+        pa_make_secure_parent_dir(fn);
+        
+        if ((fd = open(fn, mode, S_IRUSR|S_IWUSR)) < 0) {
+            if (mode != O_RDONLY || errno != ENOENT)
+                pa_log(__FILE__": WARNING: failed to open PID file '%s': %s\n", fn, strerror(errno));
+            goto fail;
+        }
+
+        /* Try to lock the file. If that fails, go without */
+        if (pa_lock_fd(fd, 1) < 0)
+            goto fail;
+        
+        if (fstat(fd, &st) < 0) {
+            pa_log(__FILE__": Failed to fstat() PID file '%s': %s\n", fn, strerror(errno));
+            goto fail;
+        }
+
+        /* Does the file still exist in the file system? When ye, w're done, otherwise restart */
+        if (st.st_nlink >= 1)
+            break;
+
+        if (pa_lock_fd(fd, 0) < 0)
+            goto fail;
+
+        if (close(fd) < 0) {
+            pa_log(__FILE__": Failed to close file '%s': %s\n", fn, strerror(errno));
+            goto fail;
+        }
+
+        fd = -1;
+    }
+
+    return fd;
+
+fail:
+
+    if (fd < 0) {
+        if (lock >= 0)
+            pa_lock_fd(fd, 0);
+        
+        close(fd);
+    }
+
+    return -1;
+}
+
 /* Create a new PID file for the current process. */
 int pa_pid_file_create(void) {
-    int fd = -1, lock = -1;
+    int fd = -1;
     int ret = -1;
     char fn[PATH_MAX];
     char t[20];
@@ -75,13 +128,9 @@ int pa_pid_file_create(void) {
     size_t l;
 
     pa_runtime_path("pid", fn, sizeof(fn));
-    if ((fd = open(fn, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0) {
-        pa_log(__FILE__": WARNING: failed to open PID file '%s': %s\n", fn, strerror(errno));
-        goto fail;
-    }
 
-    /* Try to lock the file. If that fails, go without */
-    lock = pa_lock_fd(fd, 1);
+    if ((fd = open_pid_file(fn, O_CREAT|O_RDWR)) < 0)
+        goto fail;
 
     if ((pid = read_pid(fn, fd)) == (pid_t) -1)
         pa_log(__FILE__": corrupt PID file, overwriting.\n");
@@ -112,9 +161,7 @@ int pa_pid_file_create(void) {
     
 fail:
     if (fd >= 0) {
-        if (lock >= 0)
-            pa_lock_fd(fd, 0);
-
+        pa_lock_fd(fd, 0);
         close(fd);
     }
     
@@ -123,19 +170,18 @@ fail:
 
 /* Remove the PID file, if it is ours */
 int pa_pid_file_remove(void) {
-    int fd = -1, lock = -1;
+    int fd = -1;
     char fn[PATH_MAX];
     int ret = -1;
     pid_t pid;
 
     pa_runtime_path("pid", fn, sizeof(fn));
-    if ((fd = open(fn, O_RDWR)) < 0) {
+
+    if ((fd = open_pid_file(fn, O_RDWR)) < 0) {
         pa_log(__FILE__": WARNING: failed to open PID file '%s': %s\n", fn, strerror(errno));
         goto fail;
     }
 
-    lock = pa_lock_fd(fd, 1);
-
     if ((pid = read_pid(fn, fd)) == (pid_t) -1)
         goto fail;
 
@@ -159,9 +205,7 @@ int pa_pid_file_remove(void) {
 fail:
 
     if (fd >= 0) {
-        if (lock >= 0)
-            pa_lock_fd(fd, 0);
-
+        pa_lock_fd(fd, 0);
         close(fd);
     }
 
@@ -180,31 +224,28 @@ int pa_pid_file_check_running(pid_t *pid) {
  * otherwise. If successful *pid contains the PID of the daemon
  * process. */
 int pa_pid_file_kill(int sig, pid_t *pid) {
-    int fd = -1, lock = -1;
+    int fd = -1;
     char fn[PATH_MAX];
     int ret = -1;
     pid_t _pid;
 
     if (!pid)
         pid = &_pid;
-
+    
     pa_runtime_path("pid", fn, sizeof(fn));
-    if ((fd = open(fn, O_RDONLY)) < 0)
+    
+    if ((fd = open_pid_file(fn, O_RDONLY)) < 0)
         goto fail;
-
-    lock = pa_lock_fd(fd, 1);
-
+    
     if ((*pid = read_pid(fn, fd)) == (pid_t) -1)
         goto fail;
-
+    
     ret = kill(*pid, sig);
     
 fail:
-
+    
     if (fd >= 0) {
-        if (lock >= 0)
-            pa_lock_fd(fd, 0);
-
+        pa_lock_fd(fd, 0);
         close(fd);
     }
 
index b01b80a..87beafb 100644 (file)
@@ -646,26 +646,50 @@ char* pa_strip_nl(char *s) {
 
 /* Create a temporary lock file and lock it. */
 int pa_lock_lockfile(const char *fn) {
-    int fd;
+    int fd = -1;
     assert(fn);
 
-    if ((fd = open(fn, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0) {
-        pa_log(__FILE__": failed to create lock file '%s': %s\n", fn, strerror(errno));
-        goto fail;
-    }
+    for (;;) {
+        struct stat st;
+        
+        if ((fd = open(fn, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0) {
+            pa_log(__FILE__": failed to create lock file '%s': %s\n", fn, strerror(errno));
+            goto fail;
+        }
+        
+        if (pa_lock_fd(fd, 1) < 0) {
+            pa_log(__FILE__": failed to lock file '%s'.\n", fn);
+            goto fail;
+        }
+        
+        if (fstat(fd, &st) < 0) {
+            pa_log(__FILE__": failed to fstat() file '%s'.\n", fn);
+            goto fail;
+        }
 
-    if (pa_lock_fd(fd, 1) < 0)
-        pa_log(__FILE__": failed to lock file '%s'.\n", fn);
-        goto fail;
+        /* Check wheter the file has been removed meanwhile. When yes, restart this loop, otherwise, we're done */
+        if (st.st_nlink >= 1)
+            break;
+            
+        if (pa_lock_fd(fd, 0) < 0) {
+            pa_log(__FILE__": failed to unlock file '%s'.\n", fn);
+            goto fail;
+        }
+        
+        if (close(fd) < 0) {
+            pa_log(__FILE__": failed to close file '%s'.\n", fn);
+            goto fail;
+        }
 
+        fd = -1;
+    }
+        
     return fd;
 
 fail:
 
-    if (fd >= 0) {
-        unlink(fn);
+    if (fd >= 0)
         close(fd);
-    }
 
     return -1;
 }