Git init
[framework/multimedia/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, 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;
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
128     return fd;
129
130 fail:
131
132     if (fd >= 0) {
133         int saved_errno = errno;
134         pa_lock_fd(fd, 0);
135         pa_close(fd);
136         errno = saved_errno;
137     }
138
139     return -1;
140 }
141
142 static int proc_name_ours(pid_t pid, const char *procname) {
143 #ifdef __linux__
144     char bn[PATH_MAX];
145     FILE *f;
146
147     pa_snprintf(bn, sizeof(bn), "/proc/%lu/stat", (unsigned long) pid);
148
149     if (!(f = fopen(bn, "r"))) {
150         pa_log_info("Failed to open %s: %s", bn, pa_cstrerror(errno));
151         return -1;
152     } else {
153         char *expected;
154         pa_bool_t good;
155         char stored[64];
156
157         if (!(fgets(stored, sizeof(stored), f))) {
158             int saved_errno = feof(f) ? EINVAL : errno;
159             pa_log_info("Failed to read from %s: %s", bn, feof(f) ? "EOF" : pa_cstrerror(errno));
160             fclose(f);
161
162             errno = saved_errno;
163             return -1;
164         }
165
166         fclose(f);
167
168         expected = pa_sprintf_malloc("%lu (%s)", (unsigned long) pid, procname);
169         good = pa_startswith(stored, expected);
170         pa_xfree(expected);
171
172 /*#if !defined(__OPTIMIZE__)*/
173         if (!good) {
174             /* libtool likes to rename our binary names ... */
175             expected = pa_sprintf_malloc("%lu (lt-%s)", (unsigned long) pid, procname);
176             good = pa_startswith(stored, expected);
177             pa_xfree(expected);
178         }
179 /*#endif*/
180
181         return !!good;
182     }
183 #else
184
185     return 1;
186 #endif
187
188 }
189
190 /* Create a new PID file for the current process. */
191 int pa_pid_file_create(const char *procname) {
192     int fd = -1;
193     int ret = -1;
194     char t[20];
195     pid_t pid;
196     size_t l;
197     char *fn;
198
199 #ifdef OS_IS_WIN32
200     HANDLE process;
201 #endif
202
203     if (!(fn = pa_runtime_path("pid")))
204         goto fail;
205
206     if ((fd = open_pid_file(fn, O_CREAT|O_RDWR)) < 0)
207         goto fail;
208
209     if ((pid = read_pid(fn, fd)) == (pid_t) -1)
210         pa_log_warn("Corrupt PID file, overwriting.");
211     else if (pid > 0) {
212         int ours = 1;
213
214 #ifdef OS_IS_WIN32
215         if ((process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid)) != NULL) {
216             CloseHandle(process);
217 #else
218         if (kill(pid, 0) >= 0 || errno != ESRCH) {
219 #endif
220
221             if (procname)
222                 if ((ours = proc_name_ours(pid, procname)) < 0) {
223                     pa_log_warn("Could not check to see if pid %lu is a pulseaudio process. "
224                                 "Asssuming it is and the daemon is already running.", (unsigned long) pid);
225                     goto fail;
226                 }
227
228             if (ours) {
229                 pa_log("Daemon already running.");
230                 ret = 1;
231                 goto fail;
232             }
233         }
234
235         pa_log_warn("Stale PID file, overwriting.");
236     }
237
238     /* Overwrite the current PID file */
239     if (lseek(fd, (off_t) 0, SEEK_SET) == (off_t) -1 || ftruncate(fd, (off_t) 0) < 0) {
240         pa_log("Failed to truncate PID file '%s': %s", fn, pa_cstrerror(errno));
241         goto fail;
242     }
243
244     pa_snprintf(t, sizeof(t), "%lu\n", (unsigned long) getpid());
245     l = strlen(t);
246
247     if (pa_loop_write(fd, t, l, NULL) != (ssize_t) l) {
248         pa_log("Failed to write PID file.");
249         goto fail;
250     }
251
252     ret = 0;
253
254 fail:
255     if (fd >= 0) {
256         pa_lock_fd(fd, 0);
257
258         if (pa_close(fd) < 0) {
259             pa_log("Failed to close PID file '%s': %s", fn, pa_cstrerror(errno));
260             ret = -1;
261         }
262     }
263
264     pa_xfree(fn);
265
266     return ret;
267 }
268
269 /* Remove the PID file, if it is ours */
270 int pa_pid_file_remove(void) {
271     int fd = -1;
272     char *fn;
273     int ret = -1;
274     pid_t pid;
275
276     if (!(fn = pa_runtime_path("pid")))
277         goto fail;
278
279     if ((fd = open_pid_file(fn, O_RDWR)) < 0) {
280         pa_log_warn("Failed to open PID file '%s': %s", fn, pa_cstrerror(errno));
281         goto fail;
282     }
283
284     if ((pid = read_pid(fn, fd)) == (pid_t) -1)
285         goto fail;
286
287     if (pid != getpid()) {
288         pa_log("PID file '%s' not mine!", fn);
289         goto fail;
290     }
291
292     if (ftruncate(fd, (off_t) 0) < 0) {
293         pa_log_warn("Failed to truncate PID file '%s': %s", fn, pa_cstrerror(errno));
294         goto fail;
295     }
296
297 #ifdef OS_IS_WIN32
298     pa_lock_fd(fd, 0);
299     pa_close(fd);
300     fd = -1;
301 #endif
302
303     if (unlink(fn) < 0) {
304         pa_log_warn("Failed to remove PID file '%s': %s", fn, pa_cstrerror(errno));
305         goto fail;
306     }
307
308     ret = 0;
309
310 fail:
311
312     if (fd >= 0) {
313         pa_lock_fd(fd, 0);
314
315         if (pa_close(fd) < 0) {
316             pa_log_warn("Failed to close PID file '%s': %s", fn, pa_cstrerror(errno));
317             ret = -1;
318         }
319     }
320
321     pa_xfree(fn);
322
323     return ret;
324 }
325
326 /* Check whether the daemon is currently running, i.e. if a PID file
327  * exists and the PID therein too. Returns 0 on succcess, -1
328  * otherwise. If pid is non-NULL and a running daemon was found,
329  * return its PID therein */
330 int pa_pid_file_check_running(pid_t *pid, const char *procname) {
331     return pa_pid_file_kill(0, pid, procname);
332 }
333
334 #ifndef OS_IS_WIN32
335
336 /* Kill a current running daemon. Return non-zero on success, -1
337  * otherwise. If successful *pid contains the PID of the daemon
338  * process. */
339 int pa_pid_file_kill(int sig, pid_t *pid, const char *procname) {
340     int fd = -1;
341     char *fn;
342     int ret = -1;
343     pid_t _pid;
344 #ifdef __linux__
345     char *e = NULL;
346 #endif
347
348     if (!pid)
349         pid = &_pid;
350
351     if (!(fn = pa_runtime_path("pid")))
352         goto fail;
353
354     if ((fd = open_pid_file(fn, O_RDONLY)) < 0) {
355
356         if (errno == ENOENT)
357             errno = ESRCH;
358
359         goto fail;
360     }
361
362     if ((*pid = read_pid(fn, fd)) == (pid_t) -1)
363         goto fail;
364
365     if (procname) {
366         int ours;
367
368         if ((ours = proc_name_ours(*pid, procname)) < 0)
369             goto fail;
370
371         if (!ours) {
372             errno = ESRCH;
373             goto fail;
374         }
375     }
376
377     ret = kill(*pid, sig);
378
379 fail:
380
381     if (fd >= 0) {
382         int saved_errno = errno;
383         pa_lock_fd(fd, 0);
384         pa_close(fd);
385         errno = saved_errno;
386     }
387
388 #ifdef __linux__
389     pa_xfree(e);
390 #endif
391
392     pa_xfree(fn);
393
394     return ret;
395
396 }
397
398 #else /* OS_IS_WIN32 */
399
400 int pa_pid_file_kill(int sig, pid_t *pid, const char *exe_name) {
401     return -1;
402 }
403
404 #endif