• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
read_pid(const char * fn,int fd)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 
open_pid_file(const char * fn,int mode)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 
proc_name_ours(pid_t pid,const char * procname)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. */
pa_pid_file_create(const char * procname)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
399