2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
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.
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.
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
30 #include <sys/types.h>
42 #include <pulse/xmalloc.h>
43 #include <pulse/util.h>
45 #include <pulsecore/core-error.h>
46 #include <pulsecore/core-util.h>
47 #include <pulsecore/log.h>
48 #include <pulsecore/macro.h>
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
) {
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
));
71 if ((e
= strchr(t
, '\n')))
74 if (pa_atou(t
, &pid
) < 0) {
75 pa_log_warn("Failed to parse PID file '%s'", fn
);
83 static int open_pid_file(const char *fn
, int mode
) {
91 if ((fd
= pa_open_cloexec(fn
, mode
97 if (mode
!= O_RDONLY
|| errno
!= ENOENT
)
98 pa_log_warn("Failed to open PID file '%s': %s", fn
, pa_cstrerror(errno
));
102 /* Try to lock the file. If that fails, go without */
103 if (pa_lock_fd(fd
, 1) < 0)
106 if (fstat(fd
, &st
) < 0) {
107 pa_log_warn("Failed to fstat() PID file '%s': %s", fn
, pa_cstrerror(errno
));
111 /* Does the file still exist in the file system? When yes, we're done, otherwise restart */
112 if (st
.st_nlink
>= 1)
115 if (pa_lock_fd(fd
, 0) < 0)
118 if (pa_close(fd
) < 0) {
119 pa_log_warn("Failed to close file '%s': %s", fn
, pa_cstrerror(errno
));
130 int saved_errno
= errno
;
139 static int proc_name_ours(pid_t pid
, const char *procname
) {
144 pa_snprintf(bn
, sizeof(bn
), "/proc/%lu/stat", (unsigned long) pid
);
146 if (!(f
= fopen(bn
, "r"))) {
147 pa_log_info("Failed to open %s: %s", bn
, pa_cstrerror(errno
));
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
));
165 expected
= pa_sprintf_malloc("%lu (%s)", (unsigned long) pid
, procname
);
166 good
= pa_startswith(stored
, expected
);
169 /*#if !defined(__OPTIMIZE__)*/
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
);
187 /* Create a new PID file for the current process. */
188 int pa_pid_file_create(const char *procname
) {
200 if (!(fn
= pa_runtime_path("pid")))
203 if ((fd
= open_pid_file(fn
, O_CREAT
|O_RDWR
)) < 0)
206 if ((pid
= read_pid(fn
, fd
)) == (pid_t
) -1)
207 pa_log_warn("Corrupt PID file, overwriting.");
212 if ((process
= OpenProcess(PROCESS_QUERY_INFORMATION
, FALSE
, pid
)) != NULL
) {
213 CloseHandle(process
);
215 if (kill(pid
, 0) >= 0 || errno
!= ESRCH
) {
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
);
226 pa_log("Daemon already running.");
232 pa_log_warn("Stale PID file, overwriting.");
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
));
241 pa_snprintf(t
, sizeof(t
), "%lu\n", (unsigned long) getpid());
244 if (pa_loop_write(fd
, t
, l
, NULL
) != (ssize_t
) l
) {
245 pa_log("Failed to write PID file.");
255 if (pa_close(fd
) < 0) {
256 pa_log("Failed to close PID file '%s': %s", fn
, pa_cstrerror(errno
));
266 /* Remove the PID file, if it is ours */
267 int pa_pid_file_remove(void) {
273 if (!(fn
= pa_runtime_path("pid")))
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
));
281 if ((pid
= read_pid(fn
, fd
)) == (pid_t
) -1)
284 if (pid
!= getpid()) {
285 pa_log("PID file '%s' not mine!", fn
);
289 if (ftruncate(fd
, (off_t
) 0) < 0) {
290 pa_log_warn("Failed to truncate PID file '%s': %s", fn
, pa_cstrerror(errno
));
300 if (unlink(fn
) < 0) {
301 pa_log_warn("Failed to remove PID file '%s': %s", fn
, pa_cstrerror(errno
));
312 if (pa_close(fd
) < 0) {
313 pa_log_warn("Failed to close PID file '%s': %s", fn
, pa_cstrerror(errno
));
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
);
333 /* Kill a current running daemon. Return non-zero on success, -1
334 * otherwise. If successful *pid contains the PID of the daemon
336 int pa_pid_file_kill(int sig
, pid_t
*pid
, const char *procname
) {
348 if (!(fn
= pa_runtime_path("pid")))
351 if ((fd
= open_pid_file(fn
, O_RDONLY
)) < 0) {
359 if ((*pid
= read_pid(fn
, fd
)) == (pid_t
) -1)
365 if ((ours
= proc_name_ours(*pid
, procname
)) < 0)
374 ret
= kill(*pid
, sig
);
379 int saved_errno
= errno
;
395 #else /* OS_IS_WIN32 */
397 int pa_pid_file_kill(int sig
, pid_t
*pid
, const char *exe_name
) {