]> code.delx.au - pulseaudio/blob - src/pulsecore/pid.c
add new switch --start to the PA binary which allows starting PA if it is not running...
[pulseaudio] / src / pulsecore / pid.c
1 /* $Id$ */
2
3 /***
4 This file is part of PulseAudio.
5
6 Copyright 2004-2006 Lennart Poettering
7 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
8
9 PulseAudio is free software; you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version.
13
14 PulseAudio is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public
20 License along with PulseAudio; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 USA.
23 ***/
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <errno.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <string.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <limits.h>
38 #include <signal.h>
39
40 #ifdef HAVE_WINDOWS_H
41 #include <windows.h>
42 #endif
43
44 #include <pulse/xmalloc.h>
45 #include <pulse/util.h>
46
47 #include <pulsecore/core-error.h>
48 #include <pulsecore/core-util.h>
49 #include <pulsecore/log.h>
50 #include <pulsecore/macro.h>
51
52 #include "pid.h"
53
54 /* Read the PID data from the file descriptor fd, and return it. If no
55 * pid could be read, return 0, on failure (pid_t) -1 */
56 static pid_t read_pid(const char *fn, int fd) {
57 ssize_t r;
58 char t[20], *e;
59 uint32_t pid;
60
61 pa_assert(fn);
62 pa_assert(fd >= 0);
63
64 if ((r = pa_loop_read(fd, t, sizeof(t)-1, NULL)) < 0) {
65 pa_log_warn("Failed to read PID file '%s': %s", fn, pa_cstrerror(errno));
66 return (pid_t) -1;
67 }
68
69 if (r == 0)
70 return (pid_t) 0;
71
72 t[r] = 0;
73 if ((e = strchr(t, '\n')))
74 *e = 0;
75
76 if (pa_atou(t, &pid) < 0) {
77 pa_log_warn("Failed to parse PID file '%s'", fn);
78 return (pid_t) -1;
79 }
80
81 return (pid_t) pid;
82 }
83
84 static int open_pid_file(const char *fn, int mode) {
85 int fd = -1;
86
87 pa_assert(fn);
88
89 for (;;) {
90 struct stat st;
91
92 if ((fd = open(fn, mode
93 #ifdef O_NOCTTY
94 |O_NOCTTY
95 #endif
96 #ifdef O_NOFOLLOW
97 |O_NOFOLLOW
98 #endif
99 , S_IRUSR|S_IWUSR
100 )) < 0) {
101 if (mode != O_RDONLY || errno != ENOENT)
102 pa_log_warn("Failed to open PID file '%s': %s", fn, pa_cstrerror(errno));
103 goto fail;
104 }
105
106 /* Try to lock the file. If that fails, go without */
107 if (pa_lock_fd(fd, 1) < 0)
108 goto fail;
109
110 if (fstat(fd, &st) < 0) {
111 pa_log_warn("Failed to fstat() PID file '%s': %s", fn, pa_cstrerror(errno));
112 goto fail;
113 }
114
115 /* Does the file still exist in the file system? When ye, w're done, otherwise restart */
116 if (st.st_nlink >= 1)
117 break;
118
119 if (pa_lock_fd(fd, 0) < 0)
120 goto fail;
121
122 if (pa_close(fd) < 0) {
123 pa_log_warn("Failed to close file '%s': %s", fn, pa_cstrerror(errno));
124 fd = -1;
125 goto fail;
126 }
127
128 fd = -1;
129 }
130
131 return fd;
132
133 fail:
134
135 if (fd >= 0) {
136 pa_lock_fd(fd, 0);
137 pa_close(fd);
138 }
139
140 return -1;
141 }
142
143 static int proc_name_ours(pid_t pid, const char *procname) {
144 #ifdef __linux__
145 char bn[PATH_MAX];
146 FILE *f;
147
148 pa_snprintf(bn, sizeof(bn), "/proc/%lu/stat", (unsigned long) pid);
149
150 if (!(f = fopen(bn, "r"))) {
151 pa_log_info("Failed to open %s: %s", bn, pa_cstrerror(errno));
152 return -1;
153 } else {
154 char *expected;
155 pa_bool_t good;
156 char stored[64];
157
158 if (!(fgets(stored, sizeof(stored), f))) {
159 pa_log_info("Failed to read from %s: %s", bn, feof(f) ? "EOF" : pa_cstrerror(errno));
160 fclose(f);
161 return -1;
162 }
163
164 fclose(f);
165
166 expected = pa_sprintf_malloc("%lu (%s)", (unsigned long) pid, procname);
167 good = pa_startswith(stored, expected);
168 pa_xfree(expected);
169
170 #if !defined(__OPTIMIZE__)
171 if (!good) {
172 /* libtool likes to rename our binary names ... */
173 expected = pa_sprintf_malloc("%lu (lt-%s)", (unsigned long) pid, procname);
174 good = pa_startswith(stored, expected);
175 pa_xfree(expected);
176 }
177 #endif
178
179 return !!good;
180 }
181 #endif
182
183 return 1;
184 }
185
186 /* Create a new PID file for the current process. */
187 int pa_pid_file_create(const char *procname) {
188 int fd = -1;
189 int ret = -1;
190 char t[20];
191 pid_t pid;
192 size_t l;
193 char *fn;
194
195 #ifdef OS_IS_WIN32
196 HANDLE process;
197 #endif
198
199 if (!(fn = pa_runtime_path("pid")))
200 goto fail;
201
202 if ((fd = open_pid_file(fn, O_CREAT|O_RDWR)) < 0)
203 goto fail;
204
205 if ((pid = read_pid(fn, fd)) == (pid_t) -1)
206 pa_log_warn("Corrupt PID file, overwriting.");
207 else if (pid > 0) {
208
209 #ifdef OS_IS_WIN32
210 if ((process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid)) != NULL) {
211 CloseHandle(process);
212 #else
213 if (kill(pid, 0) >= 0 || errno != ESRCH) {
214 #endif
215 int ours = 1;
216
217 if (procname)
218 if ((ours = proc_name_ours(pid, procname)) < 0)
219 goto fail;
220
221 if (ours) {
222 pa_log("Daemon already running.");
223 ret = 1;
224 goto fail;
225 }
226 }
227
228 pa_log_warn("Stale PID file, overwriting.");
229 }
230
231 /* Overwrite the current PID file */
232 if (lseek(fd, 0, SEEK_SET) == (off_t) -1 || ftruncate(fd, 0) < 0) {
233 pa_log("Failed to truncate PID file '%s': %s", fn, pa_cstrerror(errno));
234 goto fail;
235 }
236
237 pa_snprintf(t, sizeof(t), "%lu\n", (unsigned long) getpid());
238 l = strlen(t);
239
240 if (pa_loop_write(fd, t, l, NULL) != (ssize_t) l) {
241 pa_log("Failed to write PID file.");
242 goto fail;
243 }
244
245 ret = 0;
246
247 fail:
248 if (fd >= 0) {
249 pa_lock_fd(fd, 0);
250
251 if (pa_close(fd) < 0) {
252 pa_log("Failed to close PID file '%s': %s", fn, pa_cstrerror(errno));
253 ret = -1;
254 }
255 }
256
257 pa_xfree(fn);
258
259 return ret;
260 }
261
262 /* Remove the PID file, if it is ours */
263 int pa_pid_file_remove(void) {
264 int fd = -1;
265 char *fn;
266 int ret = -1;
267 pid_t pid;
268
269 if (!(fn = pa_runtime_path("pid")))
270 goto fail;
271
272 if ((fd = open_pid_file(fn, O_RDWR)) < 0) {
273 pa_log_warn("Failed to open PID file '%s': %s", fn, pa_cstrerror(errno));
274 goto fail;
275 }
276
277 if ((pid = read_pid(fn, fd)) == (pid_t) -1)
278 goto fail;
279
280 if (pid != getpid()) {
281 pa_log("PID file '%s' not mine!", fn);
282 goto fail;
283 }
284
285 if (ftruncate(fd, 0) < 0) {
286 pa_log_warn("Failed to truncate PID file '%s': %s", fn, pa_cstrerror(errno));
287 goto fail;
288 }
289
290 #ifdef OS_IS_WIN32
291 pa_lock_fd(fd, 0);
292 pa_close(fd);
293 fd = -1;
294 #endif
295
296 if (unlink(fn) < 0) {
297 pa_log_warn("Failed to remove PID file '%s': %s", fn, pa_cstrerror(errno));
298 goto fail;
299 }
300
301 ret = 0;
302
303 fail:
304
305 if (fd >= 0) {
306 pa_lock_fd(fd, 0);
307
308 if (pa_close(fd) < 0) {
309 pa_log_warn("Failed to close PID file '%s': %s", fn, pa_cstrerror(errno));
310 ret = -1;
311 }
312 }
313
314 pa_xfree(fn);
315
316 return ret;
317 }
318
319 /* Check whether the daemon is currently running, i.e. if a PID file
320 * exists and the PID therein too. Returns 0 on succcess, -1
321 * otherwise. If pid is non-NULL and a running daemon was found,
322 * return its PID therein */
323 int pa_pid_file_check_running(pid_t *pid, const char *procname) {
324 return pa_pid_file_kill(0, pid, procname);
325 }
326
327 #ifndef OS_IS_WIN32
328
329 /* Kill a current running daemon. Return non-zero on success, -1
330 * otherwise. If successful *pid contains the PID of the daemon
331 * process. */
332 int pa_pid_file_kill(int sig, pid_t *pid, const char *procname) {
333 int fd = -1;
334 char *fn;
335 int ret = -1;
336 pid_t _pid;
337 #ifdef __linux__
338 char *e = NULL;
339 #endif
340
341 if (!pid)
342 pid = &_pid;
343
344 if (!(fn = pa_runtime_path("pid")))
345 goto fail;
346
347 if ((fd = open_pid_file(fn, O_RDONLY)) < 0)
348 goto fail;
349
350 if ((*pid = read_pid(fn, fd)) == (pid_t) -1)
351 goto fail;
352
353 if (procname) {
354 int ours;
355
356 if ((ours = proc_name_ours(*pid, procname)) < 0)
357 goto fail;
358
359 if (!ours)
360 goto fail;
361 }
362
363 ret = kill(*pid, sig);
364
365 fail:
366
367 if (fd >= 0) {
368 pa_lock_fd(fd, 0);
369 pa_close(fd);
370 }
371
372 #ifdef __linux__
373 pa_xfree(e);
374 #endif
375
376 pa_xfree(fn);
377
378 return ret;
379
380 }
381
382 #else /* OS_IS_WIN32 */
383
384 int pa_pid_file_kill(int sig, pid_t *pid, const char *exe_name) {
385 return -1;
386 }
387
388 #endif