Merge commit 'origin/master-tx'
[profile/ivi/pulseaudio-panda.git] / src / pulsecore / pid.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2004-2006 Lennart Poettering
5   Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
7   PulseAudio is free software; you can redistribute it and/or modify
8   it under the terms of the GNU Lesser General Public License as
9   published by the Free Software Foundation; either version 2.1 of the
10   License, or (at your option) any later version.
11
12   PulseAudio is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   General Public License for more details.
16
17   You should have received a copy of the GNU Lesser General Public
18   License along with PulseAudio; if not, write to the Free Software
19   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20   USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <fcntl.h>
28 #include <unistd.h>
29 #include <errno.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <string.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <limits.h>
36 #include <signal.h>
37
38 #ifdef HAVE_WINDOWS_H
39 #include <windows.h>
40 #endif
41
42 #include <pulse/xmalloc.h>
43 #include <pulse/util.h>
44
45 #include <pulsecore/core-error.h>
46 #include <pulsecore/core-util.h>
47 #include <pulsecore/log.h>
48 #include <pulsecore/macro.h>
49
50 #include "pid.h"
51
52 /* Read the PID data from the file descriptor fd, and return it. If no
53  * pid could be read, return 0, on failure (pid_t) -1 */
54 static pid_t read_pid(const char *fn, int fd) {
55     ssize_t r;
56     char t[20], *e;
57     uint32_t pid;
58
59     pa_assert(fn);
60     pa_assert(fd >= 0);
61
62     if ((r = pa_loop_read(fd, t, sizeof(t)-1, NULL)) < 0) {
63         pa_log_warn("Failed to read PID file '%s': %s", fn, pa_cstrerror(errno));
64         return (pid_t) -1;
65     }
66
67     if (r == 0)
68         return (pid_t) 0;
69
70     t[r] = 0;
71     if ((e = strchr(t, '\n')))
72         *e = 0;
73
74     if (pa_atou(t, &pid) < 0) {
75         pa_log_warn("Failed to parse PID file '%s'", fn);
76         errno = EINVAL;
77         return (pid_t) -1;
78     }
79
80     return (pid_t) pid;
81 }
82
83 static int open_pid_file(const char *fn, int mode) {
84     int fd = -1;
85
86     pa_assert(fn);
87
88     for (;;) {
89         struct stat st;
90
91         if ((fd = open(fn, mode
92 #ifdef O_NOCTTY
93                        |O_NOCTTY
94 #endif
95 #ifdef O_NOFOLLOW
96                        |O_NOFOLLOW
97 #endif
98                        , S_IRUSR|S_IWUSR
99              )) < 0) {
100             if (mode != O_RDONLY || errno != ENOENT)
101                 pa_log_warn("Failed to open PID file '%s': %s", fn, pa_cstrerror(errno));
102             goto fail;
103         }
104
105         /* Try to lock the file. If that fails, go without */
106         if (pa_lock_fd(fd, 1) < 0)
107             goto fail;
108
109         if (fstat(fd, &st) < 0) {
110             pa_log_warn("Failed to fstat() PID file '%s': %s", fn, pa_cstrerror(errno));
111             goto fail;
112         }
113
114         /* Does the file still exist in the file system? When yes, we're done, otherwise restart */
115         if (st.st_nlink >= 1)
116             break;
117
118         if (pa_lock_fd(fd, 0) < 0)
119             goto fail;
120
121         if (pa_close(fd) < 0) {
122             pa_log_warn("Failed to close file '%s': %s", fn, pa_cstrerror(errno));
123             fd = -1;
124             goto fail;
125         }
126
127         fd = -1;
128     }
129
130     return fd;
131
132 fail:
133
134     if (fd >= 0) {
135         int saved_errno = errno;
136         pa_lock_fd(fd, 0);
137         pa_close(fd);
138         errno = saved_errno;
139     }
140
141     return -1;
142 }
143
144 static int proc_name_ours(pid_t pid, const char *procname) {
145 #ifdef __linux__
146     char bn[PATH_MAX];
147     FILE *f;
148
149     pa_snprintf(bn, sizeof(bn), "/proc/%lu/stat", (unsigned long) pid);
150
151     if (!(f = fopen(bn, "r"))) {
152         pa_log_info("Failed to open %s: %s", bn, pa_cstrerror(errno));
153         return -1;
154     } else {
155         char *expected;
156         pa_bool_t good;
157         char stored[64];
158
159         if (!(fgets(stored, sizeof(stored), f))) {
160             int saved_errno = feof(f) ? EINVAL : errno;
161             pa_log_info("Failed to read from %s: %s", bn, feof(f) ? "EOF" : pa_cstrerror(errno));
162             fclose(f);
163
164             errno = saved_errno;
165             return -1;
166         }
167
168         fclose(f);
169
170         expected = pa_sprintf_malloc("%lu (%s)", (unsigned long) pid, procname);
171         good = pa_startswith(stored, expected);
172         pa_xfree(expected);
173
174 /*#if !defined(__OPTIMIZE__)*/
175         if (!good) {
176             /* libtool likes to rename our binary names ... */
177             expected = pa_sprintf_malloc("%lu (lt-%s)", (unsigned long) pid, procname);
178             good = pa_startswith(stored, expected);
179             pa_xfree(expected);
180         }
181 /*#endif*/
182
183         return !!good;
184     }
185 #else
186
187     return 1;
188 #endif
189
190 }
191
192 /* Create a new PID file for the current process. */
193 int pa_pid_file_create(const char *procname) {
194     int fd = -1;
195     int ret = -1;
196     char t[20];
197     pid_t pid;
198     size_t l;
199     char *fn;
200
201 #ifdef OS_IS_WIN32
202     HANDLE process;
203 #endif
204
205     if (!(fn = pa_runtime_path("pid")))
206         goto fail;
207
208     if ((fd = open_pid_file(fn, O_CREAT|O_RDWR)) < 0)
209         goto fail;
210
211     if ((pid = read_pid(fn, fd)) == (pid_t) -1)
212         pa_log_warn("Corrupt PID file, overwriting.");
213     else if (pid > 0) {
214         int ours = 1;
215
216 #ifdef OS_IS_WIN32
217         if ((process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid)) != NULL) {
218             CloseHandle(process);
219 #else
220         if (kill(pid, 0) >= 0 || errno != ESRCH) {
221 #endif
222
223             if (procname)
224                 if ((ours = proc_name_ours(pid, procname)) < 0) {
225                     pa_log_warn("Could not check to see if pid %lu is a pulseaudio process. "
226                                 "Asssuming it is and the daemon is already running.", (unsigned long) pid);
227                     goto fail;
228                 }
229
230             if (ours) {
231                 pa_log("Daemon already running.");
232                 ret = 1;
233                 goto fail;
234             }
235         }
236
237         pa_log_warn("Stale PID file, overwriting.");
238     }
239
240     /* Overwrite the current PID file */
241     if (lseek(fd, (off_t) 0, SEEK_SET) == (off_t) -1 || ftruncate(fd, (off_t) 0) < 0) {
242         pa_log("Failed to truncate PID file '%s': %s", fn, pa_cstrerror(errno));
243         goto fail;
244     }
245
246     pa_snprintf(t, sizeof(t), "%lu\n", (unsigned long) getpid());
247     l = strlen(t);
248
249     if (pa_loop_write(fd, t, l, NULL) != (ssize_t) l) {
250         pa_log("Failed to write PID file.");
251         goto fail;
252     }
253
254     ret = 0;
255
256 fail:
257     if (fd >= 0) {
258         pa_lock_fd(fd, 0);
259
260         if (pa_close(fd) < 0) {
261             pa_log("Failed to close PID file '%s': %s", fn, pa_cstrerror(errno));
262             ret = -1;
263         }
264     }
265
266     pa_xfree(fn);
267
268     return ret;
269 }
270
271 /* Remove the PID file, if it is ours */
272 int pa_pid_file_remove(void) {
273     int fd = -1;
274     char *fn;
275     int ret = -1;
276     pid_t pid;
277
278     if (!(fn = pa_runtime_path("pid")))
279         goto fail;
280
281     if ((fd = open_pid_file(fn, O_RDWR)) < 0) {
282         pa_log_warn("Failed to open PID file '%s': %s", fn, pa_cstrerror(errno));
283         goto fail;
284     }
285
286     if ((pid = read_pid(fn, fd)) == (pid_t) -1)
287         goto fail;
288
289     if (pid != getpid()) {
290         pa_log("PID file '%s' not mine!", fn);
291         goto fail;
292     }
293
294     if (ftruncate(fd, (off_t) 0) < 0) {
295         pa_log_warn("Failed to truncate PID file '%s': %s", fn, pa_cstrerror(errno));
296         goto fail;
297     }
298
299 #ifdef OS_IS_WIN32
300     pa_lock_fd(fd, 0);
301     pa_close(fd);
302     fd = -1;
303 #endif
304
305     if (unlink(fn) < 0) {
306         pa_log_warn("Failed to remove PID file '%s': %s", fn, pa_cstrerror(errno));
307         goto fail;
308     }
309
310     ret = 0;
311
312 fail:
313
314     if (fd >= 0) {
315         pa_lock_fd(fd, 0);
316
317         if (pa_close(fd) < 0) {
318             pa_log_warn("Failed to close PID file '%s': %s", fn, pa_cstrerror(errno));
319             ret = -1;
320         }
321     }
322
323     pa_xfree(fn);
324
325     return ret;
326 }
327
328 /* Check whether the daemon is currently running, i.e. if a PID file
329  * exists and the PID therein too. Returns 0 on succcess, -1
330  * otherwise. If pid is non-NULL and a running daemon was found,
331  * return its PID therein */
332 int pa_pid_file_check_running(pid_t *pid, const char *procname) {
333     return pa_pid_file_kill(0, pid, procname);
334 }
335
336 #ifndef OS_IS_WIN32
337
338 /* Kill a current running daemon. Return non-zero on success, -1
339  * otherwise. If successful *pid contains the PID of the daemon
340  * process. */
341 int pa_pid_file_kill(int sig, pid_t *pid, const char *procname) {
342     int fd = -1;
343     char *fn;
344     int ret = -1;
345     pid_t _pid;
346 #ifdef __linux__
347     char *e = NULL;
348 #endif
349
350     if (!pid)
351         pid = &_pid;
352
353     if (!(fn = pa_runtime_path("pid")))
354         goto fail;
355
356     if ((fd = open_pid_file(fn, O_RDONLY)) < 0) {
357
358         if (errno == ENOENT)
359             errno = ESRCH;
360
361         goto fail;
362     }
363
364     if ((*pid = read_pid(fn, fd)) == (pid_t) -1)
365         goto fail;
366
367     if (procname) {
368         int ours;
369
370         if ((ours = proc_name_ours(*pid, procname)) < 0)
371             goto fail;
372
373         if (!ours) {
374             errno = ESRCH;
375             goto fail;
376         }
377     }
378
379     ret = kill(*pid, sig);
380
381 fail:
382
383     if (fd >= 0) {
384         int saved_errno = errno;
385         pa_lock_fd(fd, 0);
386         pa_close(fd);
387         errno = saved_errno;
388     }
389
390 #ifdef __linux__
391     pa_xfree(e);
392 #endif
393
394     pa_xfree(fn);
395
396     return ret;
397
398 }
399
400 #else /* OS_IS_WIN32 */
401
402 int pa_pid_file_kill(int sig, pid_t *pid, const char *exe_name) {
403     return -1;
404 }
405
406 #endif