]> code.delx.au - pulseaudio/blob - src/pulsecore/pid.c
remap: Change remapping function argument type from void to int16_t / float as approp...
[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
44 #include <pulsecore/core-error.h>
45 #include <pulsecore/core-util.h>
46 #include <pulsecore/log.h>
47 #include <pulsecore/macro.h>
48
49 #include "pid.h"
50
51 /* Read the PID data from the file descriptor fd, and return it. If no
52 * pid could be read, return 0, on failure (pid_t) -1 */
53 static pid_t read_pid(const char *fn, int fd) {
54 ssize_t r;
55 char t[20], *e;
56 uint32_t pid;
57
58 pa_assert(fn);
59 pa_assert(fd >= 0);
60
61 if ((r = pa_loop_read(fd, t, sizeof(t)-1, NULL)) < 0) {
62 pa_log_warn("Failed to read PID file '%s': %s", fn, pa_cstrerror(errno));
63 return (pid_t) -1;
64 }
65
66 if (r == 0)
67 return (pid_t) 0;
68
69 t[r] = 0;
70 if ((e = strchr(t, '\n')))
71 *e = 0;
72
73 if (pa_atou(t, &pid) < 0) {
74 pa_log_warn("Failed to parse PID file '%s'", fn);
75 errno = EINVAL;
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;
84
85 pa_assert(fn);
86
87 for (;;) {
88 struct stat st;
89
90 if ((fd = pa_open_cloexec(fn, mode
91 #ifdef O_NOFOLLOW
92 |O_NOFOLLOW
93 #endif
94 , S_IRUSR|S_IWUSR
95 )) < 0) {
96 if (mode != O_RDONLY || errno != ENOENT)
97 pa_log_warn("Failed to open PID file '%s': %s", fn, pa_cstrerror(errno));
98 goto fail;
99 }
100
101 /* Try to lock the file. If that fails, go without */
102 if (pa_lock_fd(fd, 1) < 0)
103 goto fail;
104
105 if (fstat(fd, &st) < 0) {
106 pa_log_warn("Failed to fstat() PID file '%s': %s", fn, pa_cstrerror(errno));
107 goto fail;
108 }
109
110 /* Does the file still exist in the file system? When yes, we're done, otherwise restart */
111 if (st.st_nlink >= 1)
112 break;
113
114 if (pa_lock_fd(fd, 0) < 0)
115 goto fail;
116
117 if (pa_close(fd) < 0) {
118 pa_log_warn("Failed to close file '%s': %s", fn, pa_cstrerror(errno));
119 fd = -1;
120 goto fail;
121 }
122 }
123
124 return fd;
125
126 fail:
127
128 if (fd >= 0) {
129 int saved_errno = errno;
130 pa_lock_fd(fd, 0);
131 pa_close(fd);
132 errno = saved_errno;
133 }
134
135 return -1;
136 }
137
138 static int proc_name_ours(pid_t pid, const char *procname) {
139 #ifdef __linux__
140 char bn[PATH_MAX];
141 FILE *f;
142
143 pa_snprintf(bn, sizeof(bn), "/proc/%lu/stat", (unsigned long) pid);
144
145 if (!(f = pa_fopen_cloexec(bn, "r"))) {
146 pa_log_info("Failed to open %s: %s", bn, pa_cstrerror(errno));
147 return -1;
148 } else {
149 char *expected;
150 bool good;
151 char stored[64];
152
153 if (!(fgets(stored, sizeof(stored), f))) {
154 int saved_errno = feof(f) ? EINVAL : errno;
155 pa_log_info("Failed to read from %s: %s", bn, feof(f) ? "EOF" : pa_cstrerror(errno));
156 fclose(f);
157
158 errno = saved_errno;
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 #else
180
181 return 1;
182 #endif
183
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 int ours = 1;
209
210 #ifdef OS_IS_WIN32
211 if ((process = OpenProcess(PROCESS_QUERY_INFORMATION, false, pid)) != NULL) {
212 CloseHandle(process);
213 #else
214 if (kill(pid, 0) >= 0 || errno != ESRCH) {
215 #endif
216
217 if (procname)
218 if ((ours = proc_name_ours(pid, procname)) < 0) {
219 pa_log_warn("Could not check to see if pid %lu is a pulseaudio process. "
220 "Assuming it is and the daemon is already running.", (unsigned long) pid);
221 goto fail;
222 }
223
224 if (ours) {
225 pa_log("Daemon already running.");
226 ret = 1;
227 goto fail;
228 }
229 }
230
231 pa_log_warn("Stale PID file, overwriting.");
232 }
233
234 /* Overwrite the current PID file */
235 if (lseek(fd, (off_t) 0, SEEK_SET) == (off_t) -1 || ftruncate(fd, (off_t) 0) < 0) {
236 pa_log("Failed to truncate PID file '%s': %s", fn, pa_cstrerror(errno));
237 goto fail;
238 }
239
240 pa_snprintf(t, sizeof(t), "%lu\n", (unsigned long) getpid());
241 l = strlen(t);
242
243 if (pa_loop_write(fd, t, l, NULL) != (ssize_t) l) {
244 pa_log("Failed to write PID file.");
245 goto fail;
246 }
247
248 ret = 0;
249
250 fail:
251 if (fd >= 0) {
252 pa_lock_fd(fd, 0);
253
254 if (pa_close(fd) < 0) {
255 pa_log("Failed to close PID file '%s': %s", fn, pa_cstrerror(errno));
256 ret = -1;
257 }
258 }
259
260 pa_xfree(fn);
261
262 return ret;
263 }
264
265 /* Remove the PID file, if it is ours */
266 int pa_pid_file_remove(void) {
267 int fd = -1;
268 char *fn;
269 int ret = -1;
270 pid_t pid;
271
272 if (!(fn = pa_runtime_path("pid")))
273 goto fail;
274
275 if ((fd = open_pid_file(fn, O_RDWR)) < 0) {
276 pa_log_warn("Failed to open PID file '%s': %s", fn, pa_cstrerror(errno));
277 goto fail;
278 }
279
280 if ((pid = read_pid(fn, fd)) == (pid_t) -1)
281 goto fail;
282
283 if (pid != getpid()) {
284 pa_log("PID file '%s' not mine!", fn);
285 goto fail;
286 }
287
288 if (ftruncate(fd, (off_t) 0) < 0) {
289 pa_log_warn("Failed to truncate PID file '%s': %s", fn, pa_cstrerror(errno));
290 goto fail;
291 }
292
293 #ifdef OS_IS_WIN32
294 pa_lock_fd(fd, 0);
295 pa_close(fd);
296 fd = -1;
297 #endif
298
299 if (unlink(fn) < 0) {
300 pa_log_warn("Failed to remove PID file '%s': %s", fn, pa_cstrerror(errno));
301 goto fail;
302 }
303
304 ret = 0;
305
306 fail:
307
308 if (fd >= 0) {
309 pa_lock_fd(fd, 0);
310
311 if (pa_close(fd) < 0) {
312 pa_log_warn("Failed to close PID file '%s': %s", fn, pa_cstrerror(errno));
313 ret = -1;
314 }
315 }
316
317 pa_xfree(fn);
318
319 return ret;
320 }
321
322 /* Check whether the daemon is currently running, i.e. if a PID file
323 * exists and the PID therein too. Returns 0 on success, -1
324 * otherwise. If pid is non-NULL and a running daemon was found,
325 * return its PID therein */
326 int pa_pid_file_check_running(pid_t *pid, const char *procname) {
327 return pa_pid_file_kill(0, pid, procname);
328 }
329
330 #ifndef OS_IS_WIN32
331
332 /* Kill a current running daemon. Return non-zero on success, -1
333 * otherwise. If successful *pid contains the PID of the daemon
334 * process. */
335 int pa_pid_file_kill(int sig, pid_t *pid, const char *procname) {
336 int fd = -1;
337 char *fn;
338 int ret = -1;
339 pid_t _pid;
340 #ifdef __linux__
341 char *e = NULL;
342 #endif
343
344 if (!pid)
345 pid = &_pid;
346
347 if (!(fn = pa_runtime_path("pid")))
348 goto fail;
349
350 if ((fd = open_pid_file(fn, O_RDONLY)) < 0) {
351
352 if (errno == ENOENT)
353 errno = ESRCH;
354
355 goto fail;
356 }
357
358 if ((*pid = read_pid(fn, fd)) == (pid_t) -1)
359 goto fail;
360
361 if (procname) {
362 int ours;
363
364 if ((ours = proc_name_ours(*pid, procname)) < 0)
365 goto fail;
366
367 if (!ours) {
368 errno = ESRCH;
369 goto fail;
370 }
371 }
372
373 ret = kill(*pid, sig);
374
375 fail:
376
377 if (fd >= 0) {
378 int saved_errno = errno;
379 pa_lock_fd(fd, 0);
380 pa_close(fd);
381 errno = saved_errno;
382 }
383
384 #ifdef __linux__
385 pa_xfree(e);
386 #endif
387
388 pa_xfree(fn);
389
390 return ret;
391
392 }
393
394 #else /* OS_IS_WIN32 */
395
396 int pa_pid_file_kill(int sig, pid_t *pid, const char *exe_name) {
397 return -1;
398 }
399
400 #endif