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