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