]> code.delx.au - pulseaudio/blobdiff - src/pulsecore/pid.c
increase log buffer further
[pulseaudio] / src / pulsecore / pid.c
index 22ceae89b09daa7670c603333a3fa0557bdc99bb..008784629de97b899580773aaf42af3568276f93 100644 (file)
@@ -1,5 +1,3 @@
-/* $Id$ */
-
 /***
   This file is part of PulseAudio.
 
 /***
   This file is part of PulseAudio.
 
@@ -8,7 +6,7 @@
 
   PulseAudio is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as
 
   PulseAudio is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as
-  published by the Free Software Foundation; either version 2 of the
+  published by the Free Software Foundation; either version 2.1 of the
   License, or (at your option) any later version.
 
   PulseAudio is distributed in the hope that it will be useful, but
   License, or (at your option) any later version.
 
   PulseAudio is distributed in the hope that it will be useful, but
@@ -42,6 +40,7 @@
 #endif
 
 #include <pulse/xmalloc.h>
 #endif
 
 #include <pulse/xmalloc.h>
+#include <pulse/util.h>
 
 #include <pulsecore/core-error.h>
 #include <pulsecore/core-util.h>
 
 #include <pulsecore/core-error.h>
 #include <pulsecore/core-util.h>
@@ -61,8 +60,7 @@ static pid_t read_pid(const char *fn, int fd) {
     pa_assert(fd >= 0);
 
     if ((r = pa_loop_read(fd, t, sizeof(t)-1, NULL)) < 0) {
     pa_assert(fd >= 0);
 
     if ((r = pa_loop_read(fd, t, sizeof(t)-1, NULL)) < 0) {
-        pa_log_warn("WARNING: failed to read PID file '%s': %s",
-            fn, pa_cstrerror(errno));
+        pa_log_warn("Failed to read PID file '%s': %s", fn, pa_cstrerror(errno));
         return (pid_t) -1;
     }
 
         return (pid_t) -1;
     }
 
@@ -74,7 +72,8 @@ static pid_t read_pid(const char *fn, int fd) {
         *e = 0;
 
     if (pa_atou(t, &pid) < 0) {
         *e = 0;
 
     if (pa_atou(t, &pid) < 0) {
-        pa_log_warn("WARNING: failed to parse PID file '%s'", fn);
+        pa_log_warn("Failed to parse PID file '%s'", fn);
+        errno = EINVAL;
         return (pid_t) -1;
     }
 
         return (pid_t) -1;
     }
 
@@ -89,10 +88,17 @@ static int open_pid_file(const char *fn, int mode) {
     for (;;) {
         struct stat st;
 
     for (;;) {
         struct stat st;
 
-        if ((fd = open(fn, mode, S_IRUSR|S_IWUSR)) < 0) {
+        if ((fd = open(fn, mode
+#ifdef O_NOCTTY
+                       |O_NOCTTY
+#endif
+#ifdef O_NOFOLLOW
+                       |O_NOFOLLOW
+#endif
+                       , S_IRUSR|S_IWUSR
+             )) < 0) {
             if (mode != O_RDONLY || errno != ENOENT)
             if (mode != O_RDONLY || errno != ENOENT)
-                pa_log_warn("WARNING: failed to open PID file '%s': %s",
-                    fn, pa_cstrerror(errno));
+                pa_log_warn("Failed to open PID file '%s': %s", fn, pa_cstrerror(errno));
             goto fail;
         }
 
             goto fail;
         }
 
@@ -101,21 +107,20 @@ static int open_pid_file(const char *fn, int mode) {
             goto fail;
 
         if (fstat(fd, &st) < 0) {
             goto fail;
 
         if (fstat(fd, &st) < 0) {
-            pa_log_warn("WARNING: failed to fstat() PID file '%s': %s",
-                fn, pa_cstrerror(errno));
+            pa_log_warn("Failed to fstat() PID file '%s': %s", fn, pa_cstrerror(errno));
             goto fail;
         }
 
             goto fail;
         }
 
-        /* Does the file still exist in the file system? When ye, w're done, otherwise restart */
+        /* Does the file still exist in the file system? When yes, we're done, otherwise restart */
         if (st.st_nlink >= 1)
             break;
 
         if (pa_lock_fd(fd, 0) < 0)
             goto fail;
 
         if (st.st_nlink >= 1)
             break;
 
         if (pa_lock_fd(fd, 0) < 0)
             goto fail;
 
-        if (close(fd) < 0) {
-            pa_log_warn("WARNING: failed to close file '%s': %s",
-                fn, pa_cstrerror(errno));
+        if (pa_close(fd) < 0) {
+            pa_log_warn("Failed to close file '%s': %s", fn, pa_cstrerror(errno));
+            fd = -1;
             goto fail;
         }
 
             goto fail;
         }
 
@@ -127,51 +132,114 @@ static int open_pid_file(const char *fn, int mode) {
 fail:
 
     if (fd >= 0) {
 fail:
 
     if (fd >= 0) {
+        int saved_errno = errno;
         pa_lock_fd(fd, 0);
         pa_lock_fd(fd, 0);
-        close(fd);
+        pa_close(fd);
+        errno = saved_errno;
     }
 
     return -1;
 }
 
     }
 
     return -1;
 }
 
+static int proc_name_ours(pid_t pid, const char *procname) {
+#ifdef __linux__
+    char bn[PATH_MAX];
+    FILE *f;
+
+    pa_snprintf(bn, sizeof(bn), "/proc/%lu/stat", (unsigned long) pid);
+
+    if (!(f = fopen(bn, "r"))) {
+        pa_log_info("Failed to open %s: %s", bn, pa_cstrerror(errno));
+        return -1;
+    } else {
+        char *expected;
+        pa_bool_t good;
+        char stored[64];
+
+        if (!(fgets(stored, sizeof(stored), f))) {
+            int saved_errno = feof(f) ? EINVAL : errno;
+            pa_log_info("Failed to read from %s: %s", bn, feof(f) ? "EOF" : pa_cstrerror(errno));
+            fclose(f);
+
+            errno = saved_errno;
+            return -1;
+        }
+
+        fclose(f);
+
+        expected = pa_sprintf_malloc("%lu (%s)", (unsigned long) pid, procname);
+        good = pa_startswith(stored, expected);
+        pa_xfree(expected);
+
+/*#if !defined(__OPTIMIZE__)*/
+        if (!good) {
+            /* libtool likes to rename our binary names ... */
+            expected = pa_sprintf_malloc("%lu (lt-%s)", (unsigned long) pid, procname);
+            good = pa_startswith(stored, expected);
+            pa_xfree(expected);
+        }
+/*#endif*/
+
+        return !!good;
+    }
+#else
+
+    return 1;
+#endif
+
+}
+
 /* Create a new PID file for the current process. */
 /* Create a new PID file for the current process. */
-int pa_pid_file_create(void) {
+int pa_pid_file_create(const char *procname) {
     int fd = -1;
     int ret = -1;
     int fd = -1;
     int ret = -1;
-    char fn[PATH_MAX];
     char t[20];
     pid_t pid;
     size_t l;
     char t[20];
     pid_t pid;
     size_t l;
+    char *fn;
 
 #ifdef OS_IS_WIN32
     HANDLE process;
 #endif
 
 
 #ifdef OS_IS_WIN32
     HANDLE process;
 #endif
 
-    pa_runtime_path("pid", fn, sizeof(fn));
+    if (!(fn = pa_runtime_path("pid")))
+        goto fail;
 
     if ((fd = open_pid_file(fn, O_CREAT|O_RDWR)) < 0)
         goto fail;
 
     if ((pid = read_pid(fn, fd)) == (pid_t) -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("corrupt PID file, overwriting.");
+        pa_log_warn("Corrupt PID file, overwriting.");
     else if (pid > 0) {
     else if (pid > 0) {
+        int ours = 1;
+
 #ifdef OS_IS_WIN32
         if ((process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid)) != NULL) {
             CloseHandle(process);
 #else
         if (kill(pid, 0) >= 0 || errno != ESRCH) {
 #endif
 #ifdef OS_IS_WIN32
         if ((process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid)) != NULL) {
             CloseHandle(process);
 #else
         if (kill(pid, 0) >= 0 || errno != ESRCH) {
 #endif
-            pa_log("daemon already running.");
-            goto fail;
+
+            if (procname)
+                if ((ours = proc_name_ours(pid, procname)) < 0) {
+                    pa_log_warn("Could not check to see if pid %lu is a pulseaudio process. "
+                                "Asssuming it is and the daemon is already running.", (unsigned long) pid);
+                    goto fail;
+                }
+
+            if (ours) {
+                pa_log("Daemon already running.");
+                ret = 1;
+                goto fail;
+            }
         }
 
         }
 
-        pa_log("stale PID file, overwriting.");
+        pa_log_warn("Stale PID file, overwriting.");
     }
 
     /* Overwrite the current PID file */
     }
 
     /* Overwrite the current PID file */
-    if (lseek(fd, 0, SEEK_SET) == (off_t) -1 || ftruncate(fd, 0) < 0) {
-        pa_log("failed to truncate PID file '%s': %s",
-            fn, pa_cstrerror(errno));
+    if (lseek(fd, (off_t) 0, SEEK_SET) == (off_t) -1 || ftruncate(fd, (off_t) 0) < 0) {
+        pa_log("Failed to truncate PID file '%s': %s", fn, pa_cstrerror(errno));
         goto fail;
     }
 
         goto fail;
     }
 
@@ -179,7 +247,7 @@ int pa_pid_file_create(void) {
     l = strlen(t);
 
     if (pa_loop_write(fd, t, l, NULL) != (ssize_t) l) {
     l = strlen(t);
 
     if (pa_loop_write(fd, t, l, NULL) != (ssize_t) l) {
-        pa_log("failed to write PID file.");
+        pa_log("Failed to write PID file.");
         goto fail;
     }
 
         goto fail;
     }
 
@@ -188,24 +256,30 @@ int pa_pid_file_create(void) {
 fail:
     if (fd >= 0) {
         pa_lock_fd(fd, 0);
 fail:
     if (fd >= 0) {
         pa_lock_fd(fd, 0);
-        close(fd);
+
+        if (pa_close(fd) < 0) {
+            pa_log("Failed to close PID file '%s': %s", fn, pa_cstrerror(errno));
+            ret = -1;
+        }
     }
 
     }
 
+    pa_xfree(fn);
+
     return ret;
 }
 
 /* Remove the PID file, if it is ours */
 int pa_pid_file_remove(void) {
     int fd = -1;
     return ret;
 }
 
 /* Remove the PID file, if it is ours */
 int pa_pid_file_remove(void) {
     int fd = -1;
-    char fn[PATH_MAX];
+    char *fn;
     int ret = -1;
     pid_t pid;
 
     int ret = -1;
     pid_t pid;
 
-    pa_runtime_path("pid", fn, sizeof(fn));
+    if (!(fn = pa_runtime_path("pid")))
+        goto fail;
 
     if ((fd = open_pid_file(fn, O_RDWR)) < 0) {
 
     if ((fd = open_pid_file(fn, O_RDWR)) < 0) {
-        pa_log_warn("WARNING: failed to open PID file '%s': %s",
-            fn, pa_cstrerror(errno));
+        pa_log_warn("Failed to open PID file '%s': %s", fn, pa_cstrerror(errno));
         goto fail;
     }
 
         goto fail;
     }
 
@@ -213,25 +287,23 @@ int pa_pid_file_remove(void) {
         goto fail;
 
     if (pid != getpid()) {
         goto fail;
 
     if (pid != getpid()) {
-        pa_log("WARNING: PID file '%s' not mine!", fn);
+        pa_log("PID file '%s' not mine!", fn);
         goto fail;
     }
 
         goto fail;
     }
 
-    if (ftruncate(fd, 0) < 0) {
-        pa_log_warn("WARNING: failed to truncate PID file '%s': %s",
-            fn, pa_cstrerror(errno));
+    if (ftruncate(fd, (off_t) 0) < 0) {
+        pa_log_warn("Failed to truncate PID file '%s': %s", fn, pa_cstrerror(errno));
         goto fail;
     }
 
 #ifdef OS_IS_WIN32
     pa_lock_fd(fd, 0);
         goto fail;
     }
 
 #ifdef OS_IS_WIN32
     pa_lock_fd(fd, 0);
-    close(fd);
+    pa_close(fd);
     fd = -1;
 #endif
 
     if (unlink(fn) < 0) {
     fd = -1;
 #endif
 
     if (unlink(fn) < 0) {
-        pa_log_warn("WARNING: failed to remove PID file '%s': %s",
-            fn, pa_cstrerror(errno));
+        pa_log_warn("Failed to remove PID file '%s': %s", fn, pa_cstrerror(errno));
         goto fail;
     }
 
         goto fail;
     }
 
@@ -241,9 +313,15 @@ fail:
 
     if (fd >= 0) {
         pa_lock_fd(fd, 0);
 
     if (fd >= 0) {
         pa_lock_fd(fd, 0);
-        pa_assert_se(close(fd) == 0);
+
+        if (pa_close(fd) < 0) {
+            pa_log_warn("Failed to close PID file '%s': %s", fn, pa_cstrerror(errno));
+            ret = -1;
+        }
     }
 
     }
 
+    pa_xfree(fn);
+
     return ret;
 }
 
     return ret;
 }
 
@@ -251,8 +329,8 @@ fail:
  * exists and the PID therein too. Returns 0 on succcess, -1
  * otherwise. If pid is non-NULL and a running daemon was found,
  * return its PID therein */
  * exists and the PID therein too. Returns 0 on succcess, -1
  * otherwise. If pid is non-NULL and a running daemon was found,
  * return its PID therein */
-int pa_pid_file_check_running(pid_t *pid) {
-    return pa_pid_file_kill(0, pid);
+int pa_pid_file_check_running(pid_t *pid, const char *procname) {
+    return pa_pid_file_kill(0, pid, procname);
 }
 
 #ifndef OS_IS_WIN32
 }
 
 #ifndef OS_IS_WIN32
@@ -260,39 +338,68 @@ int pa_pid_file_check_running(pid_t *pid) {
 /* Kill a current running daemon. Return non-zero on success, -1
  * otherwise. If successful *pid contains the PID of the daemon
  * process. */
 /* Kill a current running daemon. Return non-zero on success, -1
  * otherwise. If successful *pid contains the PID of the daemon
  * process. */
-int pa_pid_file_kill(int sig, pid_t *pid) {
+int pa_pid_file_kill(int sig, pid_t *pid, const char *procname) {
     int fd = -1;
     int fd = -1;
-    char fn[PATH_MAX];
+    char *fn;
     int ret = -1;
     pid_t _pid;
     int ret = -1;
     pid_t _pid;
+#ifdef __linux__
+    char *e = NULL;
+#endif
 
     if (!pid)
         pid = &_pid;
 
 
     if (!pid)
         pid = &_pid;
 
-    pa_runtime_path("pid", fn, sizeof(fn));
+    if (!(fn = pa_runtime_path("pid")))
+        goto fail;
+
+    if ((fd = open_pid_file(fn, O_RDONLY)) < 0) {
+
+        if (errno == ENOENT)
+            errno = ESRCH;
 
 
-    if ((fd = open_pid_file(fn, O_RDONLY)) < 0)
         goto fail;
         goto fail;
+    }
 
     if ((*pid = read_pid(fn, fd)) == (pid_t) -1)
         goto fail;
 
 
     if ((*pid = read_pid(fn, fd)) == (pid_t) -1)
         goto fail;
 
+    if (procname) {
+        int ours;
+
+        if ((ours = proc_name_ours(*pid, procname)) < 0)
+            goto fail;
+
+        if (!ours) {
+            errno = ESRCH;
+            goto fail;
+        }
+    }
+
     ret = kill(*pid, sig);
 
 fail:
 
     if (fd >= 0) {
     ret = kill(*pid, sig);
 
 fail:
 
     if (fd >= 0) {
+        int saved_errno = errno;
         pa_lock_fd(fd, 0);
         pa_lock_fd(fd, 0);
-        pa_assert_se(close(fd) == 0);
+        pa_close(fd);
+        errno = saved_errno;
     }
 
     }
 
+#ifdef __linux__
+    pa_xfree(e);
+#endif
+
+    pa_xfree(fn);
+
     return ret;
 
 }
 
 #else /* OS_IS_WIN32 */
 
     return ret;
 
 }
 
 #else /* OS_IS_WIN32 */
 
-int pa_pid_file_kill(int sig, pid_t *pid) {
+int pa_pid_file_kill(int sig, pid_t *pid, const char *exe_name) {
     return -1;
 }
 
     return -1;
 }