]> code.delx.au - pulseaudio/blob - src/pulsecore/pid.c
Merge dead branch 'ossman'
[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 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 return (pid_t) -1;
77 }
78
79 return (pid_t) pid;
80 }
81
82 static int open_pid_file(const char *fn, int mode) {
83 int fd = -1;
84
85 pa_assert(fn);
86
87 for (;;) {
88 struct stat st;
89
90 if ((fd = open(fn, mode
91 #ifdef O_NOCTTY
92 |O_NOCTTY
93 #endif
94 #ifdef O_NOFOLLOW
95 |O_NOFOLLOW
96 #endif
97 , S_IRUSR|S_IWUSR
98 )) < 0) {
99 if (mode != O_RDONLY || errno != ENOENT)
100 pa_log_warn("Failed to open PID file '%s': %s", fn, pa_cstrerror(errno));
101 goto fail;
102 }
103
104 /* Try to lock the file. If that fails, go without */
105 if (pa_lock_fd(fd, 1) < 0)
106 goto fail;
107
108 if (fstat(fd, &st) < 0) {
109 pa_log_warn("Failed to fstat() PID file '%s': %s", fn, pa_cstrerror(errno));
110 goto fail;
111 }
112
113 /* Does the file still exist in the file system? When ye, w're done, otherwise restart */
114 if (st.st_nlink >= 1)
115 break;
116
117 if (pa_lock_fd(fd, 0) < 0)
118 goto fail;
119
120 if (pa_close(fd) < 0) {
121 pa_log_warn("Failed to close file '%s': %s", fn, pa_cstrerror(errno));
122 fd = -1;
123 goto fail;
124 }
125
126 fd = -1;
127 }
128
129 return fd;
130
131 fail:
132
133 if (fd >= 0) {
134 pa_lock_fd(fd, 0);
135 pa_close(fd);
136 }
137
138 return -1;
139 }
140
141 static int proc_name_ours(pid_t pid, const char *procname) {
142 #ifdef __linux__
143 char bn[PATH_MAX];
144 FILE *f;
145
146 pa_snprintf(bn, sizeof(bn), "/proc/%lu/stat", (unsigned long) pid);
147
148 if (!(f = fopen(bn, "r"))) {
149 pa_log_info("Failed to open %s: %s", bn, pa_cstrerror(errno));
150 return -1;
151 } else {
152 char *expected;
153 pa_bool_t good;
154 char stored[64];
155
156 if (!(fgets(stored, sizeof(stored), f))) {
157 pa_log_info("Failed to read from %s: %s", bn, feof(f) ? "EOF" : pa_cstrerror(errno));
158 fclose(f);
159 return -1;
160 }
161
162 fclose(f);
163
164 expected = pa_sprintf_malloc("%lu (%s)", (unsigned long) pid, procname);
165 good = pa_startswith(stored, expected);
166 pa_xfree(expected);
167
168 #if !defined(__OPTIMIZE__)
169 if (!good) {
170 /* libtool likes to rename our binary names ... */
171 expected = pa_sprintf_malloc("%lu (lt-%s)", (unsigned long) pid, procname);
172 good = pa_startswith(stored, expected);
173 pa_xfree(expected);
174 }
175 #endif
176
177 return !!good;
178 }
179 #endif
180
181 return 1;
182 }
183
184 /* Create a new PID file for the current process. */
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
207 #ifdef OS_IS_WIN32
208 if ((process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid)) != NULL) {
209 CloseHandle(process);
210 #else
211 if (kill(pid, 0) >= 0 || errno != ESRCH) {
212 #endif
213 int ours = 1;
214
215 if (procname)
216 if ((ours = proc_name_ours(pid, procname)) < 0)
217 goto fail;
218
219 if (ours) {
220 pa_log("Daemon already running.");
221 ret = 1;
222 goto fail;
223 }
224 }
225
226 pa_log_warn("Stale PID file, overwriting.");
227 }
228
229 /* Overwrite the current PID file */
230 if (lseek(fd, 0, SEEK_SET) == (off_t) -1 || ftruncate(fd, 0) < 0) {
231 pa_log("Failed to truncate PID file '%s': %s", fn, pa_cstrerror(errno));
232 goto fail;
233 }
234
235 pa_snprintf(t, sizeof(t), "%lu\n", (unsigned long) getpid());
236 l = strlen(t);
237
238 if (pa_loop_write(fd, t, l, NULL) != (ssize_t) l) {
239 pa_log("Failed to write PID file.");
240 goto fail;
241 }
242
243 ret = 0;
244
245 fail:
246 if (fd >= 0) {
247 pa_lock_fd(fd, 0);
248
249 if (pa_close(fd) < 0) {
250 pa_log("Failed to close PID file '%s': %s", fn, pa_cstrerror(errno));
251 ret = -1;
252 }
253 }
254
255 pa_xfree(fn);
256
257 return ret;
258 }
259
260 /* Remove the PID file, if it is ours */
261 int pa_pid_file_remove(void) {
262 int fd = -1;
263 char *fn;
264 int ret = -1;
265 pid_t pid;
266
267 if (!(fn = pa_runtime_path("pid")))
268 goto fail;
269
270 if ((fd = open_pid_file(fn, O_RDWR)) < 0) {
271 pa_log_warn("Failed to open PID file '%s': %s", fn, pa_cstrerror(errno));
272 goto fail;
273 }
274
275 if ((pid = read_pid(fn, fd)) == (pid_t) -1)
276 goto fail;
277
278 if (pid != getpid()) {
279 pa_log("PID file '%s' not mine!", fn);
280 goto fail;
281 }
282
283 if (ftruncate(fd, 0) < 0) {
284 pa_log_warn("Failed to truncate PID file '%s': %s", fn, pa_cstrerror(errno));
285 goto fail;
286 }
287
288 #ifdef OS_IS_WIN32
289 pa_lock_fd(fd, 0);
290 pa_close(fd);
291 fd = -1;
292 #endif
293
294 if (unlink(fn) < 0) {
295 pa_log_warn("Failed to remove PID file '%s': %s", fn, pa_cstrerror(errno));
296 goto fail;
297 }
298
299 ret = 0;
300
301 fail:
302
303 if (fd >= 0) {
304 pa_lock_fd(fd, 0);
305
306 if (pa_close(fd) < 0) {
307 pa_log_warn("Failed to close PID file '%s': %s", fn, pa_cstrerror(errno));
308 ret = -1;
309 }
310 }
311
312 pa_xfree(fn);
313
314 return ret;
315 }
316
317 /* Check whether the daemon is currently running, i.e. if a PID file
318 * exists and the PID therein too. Returns 0 on succcess, -1
319 * otherwise. If pid is non-NULL and a running daemon was found,
320 * return its PID therein */
321 int pa_pid_file_check_running(pid_t *pid, const char *procname) {
322 return pa_pid_file_kill(0, pid, procname);
323 }
324
325 #ifndef OS_IS_WIN32
326
327 /* Kill a current running daemon. Return non-zero on success, -1
328 * otherwise. If successful *pid contains the PID of the daemon
329 * process. */
330 int pa_pid_file_kill(int sig, pid_t *pid, const char *procname) {
331 int fd = -1;
332 char *fn;
333 int ret = -1;
334 pid_t _pid;
335 #ifdef __linux__
336 char *e = NULL;
337 #endif
338
339 if (!pid)
340 pid = &_pid;
341
342 if (!(fn = pa_runtime_path("pid")))
343 goto fail;
344
345 if ((fd = open_pid_file(fn, O_RDONLY)) < 0)
346 goto fail;
347
348 if ((*pid = read_pid(fn, fd)) == (pid_t) -1)
349 goto fail;
350
351 if (procname) {
352 int ours;
353
354 if ((ours = proc_name_ours(*pid, procname)) < 0)
355 goto fail;
356
357 if (!ours)
358 goto fail;
359 }
360
361 ret = kill(*pid, sig);
362
363 fail:
364
365 if (fd >= 0) {
366 pa_lock_fd(fd, 0);
367 pa_close(fd);
368 }
369
370 #ifdef __linux__
371 pa_xfree(e);
372 #endif
373
374 pa_xfree(fn);
375
376 return ret;
377
378 }
379
380 #else /* OS_IS_WIN32 */
381
382 int pa_pid_file_kill(int sig, pid_t *pid, const char *exe_name) {
383 return -1;
384 }
385
386 #endif