]> code.delx.au - pulseaudio/blob - src/pulsecore/pid.c
Merge remote branch 'origin/master-tx'
[pulseaudio] / 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