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