]> code.delx.au - pulseaudio/blobdiff - src/pulsecore/pid.c
add suspend_within_thread() callbacks to pa_sink_input/pa_source_output
[pulseaudio] / src / pulsecore / pid.c
index 6bc9f06ab20226a6174f66a487bfa8005067215f..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>
@@ -74,6 +73,7 @@ static pid_t read_pid(const char *fn, int fd) {
 
     if (pa_atou(t, &pid) < 0) {
         pa_log_warn("Failed to parse PID file '%s'", fn);
 
     if (pa_atou(t, &pid) < 0) {
         pa_log_warn("Failed to parse PID file '%s'", fn);
+        errno = EINVAL;
         return (pid_t) -1;
     }
 
         return (pid_t) -1;
     }
 
@@ -88,9 +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;
         }
 
@@ -103,7 +111,7 @@ static int open_pid_file(const char *fn, int mode) {
             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 (st.st_nlink >= 1)
             break;
 
@@ -124,27 +132,78 @@ 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_close(fd);
         pa_lock_fd(fd, 0);
         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 ((fd = open_pid_file(fn, O_CREAT|O_RDWR)) < 0)
         goto fail;
@@ -152,21 +211,34 @@ int pa_pid_file_create(void) {
     if ((pid = read_pid(fn, fd)) == (pid_t) -1)
         pa_log_warn("Corrupt PID file, overwriting.");
     else if (pid > 0) {
     if ((pid = read_pid(fn, fd)) == (pid_t) -1)
         pa_log_warn("Corrupt PID file, overwriting.");
     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_warn("Stale PID file, overwriting.");
     }
 
     /* Overwrite the current PID file */
         }
 
         pa_log_warn("Stale PID file, overwriting.");
     }
 
     /* Overwrite the current PID file */
-    if (lseek(fd, 0, SEEK_SET) == (off_t) -1 || ftruncate(fd, 0) < 0) {
+    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;
     }
         pa_log("Failed to truncate PID file '%s': %s", fn, pa_cstrerror(errno));
         goto fail;
     }
@@ -184,28 +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);
-        
+
         if (pa_close(fd) < 0) {
             pa_log("Failed to close PID file '%s': %s", fn, pa_cstrerror(errno));
             ret = -1;
         }
     }
 
         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;
     }
 
@@ -217,14 +291,14 @@ int pa_pid_file_remove(void) {
         goto fail;
     }
 
         goto fail;
     }
 
-    if (ftruncate(fd, 0) < 0) {
+    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);
         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);
-    close(fd);
+    pa_close(fd);
     fd = -1;
 #endif
 
     fd = -1;
 #endif
 
@@ -246,6 +320,8 @@ fail:
         }
     }
 
         }
     }
 
+    pa_xfree(fn);
+
     return ret;
 }
 
     return ret;
 }
 
@@ -253,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
@@ -262,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_close(fd);
         pa_lock_fd(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;
 }