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