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