diff options
| author | 2009-08-19 03:25:34 +0200 | |
|---|---|---|
| committer | 2009-08-19 03:56:09 +0200 | |
| commit | dd3258133e54bd2c3355b09f43059f56fab5ee14 (patch) | |
| tree | d28d369fa4b5e3483703862b16a4e8ef5eb1c699 /usbmuxd/main.c | |
| parent | acfba6464bd57bdd0549f083f83b12ff9909337f (diff) | |
| download | usbmuxd-dd3258133e54bd2c3355b09f43059f56fab5ee14.tar.gz usbmuxd-dd3258133e54bd2c3355b09f43059f56fab5ee14.tar.bz2 | |
Fix daemonization and lockfile madness
Diffstat (limited to 'usbmuxd/main.c')
| -rw-r--r-- | usbmuxd/main.c | 201 |
1 files changed, 140 insertions, 61 deletions
diff --git a/usbmuxd/main.c b/usbmuxd/main.c index be7451f..6b3c881 100644 --- a/usbmuxd/main.c +++ b/usbmuxd/main.c | |||
| @@ -33,7 +33,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
| 33 | #include <sys/socket.h> | 33 | #include <sys/socket.h> |
| 34 | #include <sys/un.h> | 34 | #include <sys/un.h> |
| 35 | #include <sys/stat.h> | 35 | #include <sys/stat.h> |
| 36 | #include <sys/fcntl.h> | 36 | #include <sys/types.h> |
| 37 | #include <fcntl.h> | ||
| 37 | #include <getopt.h> | 38 | #include <getopt.h> |
| 38 | #include <pwd.h> | 39 | #include <pwd.h> |
| 39 | #include <grp.h> | 40 | #include <grp.h> |
| @@ -44,7 +45,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
| 44 | #include "client.h" | 45 | #include "client.h" |
| 45 | 46 | ||
| 46 | static const char *socket_path = "/var/run/usbmuxd"; | 47 | static const char *socket_path = "/var/run/usbmuxd"; |
| 47 | static const char *lockfile = "/var/run/usbmuxd.lock"; | 48 | static const char *lockfile = "/var/run/usbmuxd.pid"; |
| 48 | 49 | ||
| 49 | int should_exit; | 50 | int should_exit; |
| 50 | 51 | ||
| @@ -55,6 +56,9 @@ static const char *drop_user = "usbmux"; | |||
| 55 | static int opt_udev = 0; | 56 | static int opt_udev = 0; |
| 56 | static int opt_exit = 0; | 57 | static int opt_exit = 0; |
| 57 | static int exit_signal = 0; | 58 | static int exit_signal = 0; |
| 59 | static int daemon_pipe; | ||
| 60 | |||
| 61 | static int report_to_parent = 0; | ||
| 58 | 62 | ||
| 59 | int create_socket(void) { | 63 | int create_socket(void) { |
| 60 | struct sockaddr_un bind_addr; | 64 | struct sockaddr_un bind_addr; |
| @@ -191,25 +195,47 @@ int main_loop(int listenfd) | |||
| 191 | /** | 195 | /** |
| 192 | * make this program run detached from the current console | 196 | * make this program run detached from the current console |
| 193 | */ | 197 | */ |
| 194 | static int daemonize() | 198 | static int daemonize(void) |
| 195 | { | 199 | { |
| 196 | pid_t pid; | 200 | pid_t pid; |
| 197 | pid_t sid; | 201 | pid_t sid; |
| 202 | int pfd[2]; | ||
| 203 | int res; | ||
| 198 | 204 | ||
| 199 | // already a daemon | 205 | // already a daemon |
| 200 | if (getppid() == 1) | 206 | if (getppid() == 1) |
| 201 | return 0; | 207 | return 0; |
| 202 | 208 | ||
| 209 | if((res = pipe(pfd)) < 0) { | ||
| 210 | usbmuxd_log(LL_FATAL, "pipe() failed."); | ||
| 211 | return res; | ||
| 212 | } | ||
| 213 | |||
| 203 | pid = fork(); | 214 | pid = fork(); |
| 204 | if (pid < 0) { | 215 | if (pid < 0) { |
| 205 | exit(EXIT_FAILURE); | 216 | usbmuxd_log(LL_FATAL, "fork() failed."); |
| 217 | return pid; | ||
| 206 | } | 218 | } |
| 207 | 219 | ||
| 208 | if (pid > 0) { | 220 | if (pid > 0) { |
| 209 | // exit parent process | 221 | // exit parent process |
| 210 | exit(EXIT_SUCCESS); | 222 | int status; |
| 223 | close(pfd[1]); | ||
| 224 | |||
| 225 | if((res = read(pfd[0],&status,sizeof(int))) != sizeof(int)) { | ||
| 226 | fprintf(stderr, "usbmuxd: ERROR: Failed to get init status from child, check syslog for messages.\n"); | ||
| 227 | exit(1); | ||
| 228 | } | ||
| 229 | if(status != 0) | ||
| 230 | fprintf(stderr, "usbmuxd: ERROR: Child process exited with error %d, check syslog for messages.\n", status); | ||
| 231 | exit(status); | ||
| 211 | } | 232 | } |
| 212 | // At this point we are executing as the child process | 233 | // At this point we are executing as the child process |
| 234 | // but we need to do one more fork | ||
| 235 | |||
| 236 | daemon_pipe = pfd[1]; | ||
| 237 | close(pfd[0]); | ||
| 238 | report_to_parent = 1; | ||
| 213 | 239 | ||
| 214 | // Change the file mode mask | 240 | // Change the file mode mask |
| 215 | umask(0); | 241 | umask(0); |
| @@ -217,23 +243,57 @@ static int daemonize() | |||
| 217 | // Create a new SID for the child process | 243 | // Create a new SID for the child process |
| 218 | sid = setsid(); | 244 | sid = setsid(); |
| 219 | if (sid < 0) { | 245 | if (sid < 0) { |
| 246 | usbmuxd_log(LL_FATAL, "setsid() failed."); | ||
| 220 | return -1; | 247 | return -1; |
| 221 | } | 248 | } |
| 249 | |||
| 250 | pid = fork(); | ||
| 251 | if (pid < 0) { | ||
| 252 | usbmuxd_log(LL_FATAL, "fork() failed (second)."); | ||
| 253 | return pid; | ||
| 254 | } | ||
| 255 | |||
| 256 | if (pid > 0) { | ||
| 257 | // exit parent process | ||
| 258 | close(daemon_pipe); | ||
| 259 | exit(0); | ||
| 260 | } | ||
| 261 | |||
| 222 | // Change the current working directory. | 262 | // Change the current working directory. |
| 223 | if ((chdir("/")) < 0) { | 263 | if ((chdir("/")) < 0) { |
| 264 | usbmuxd_log(LL_FATAL, "chdir() failed"); | ||
| 224 | return -2; | 265 | return -2; |
| 225 | } | 266 | } |
| 226 | // Redirect standard files to /dev/null | 267 | // Redirect standard files to /dev/null |
| 227 | if (!freopen("/dev/null", "r", stdin)) { | 268 | if (!freopen("/dev/null", "r", stdin)) { |
| 228 | usbmuxd_log(LL_ERROR, "ERROR: redirection of stdin failed."); | 269 | usbmuxd_log(LL_FATAL, "Redirection of stdin failed."); |
| 270 | return -3; | ||
| 229 | } | 271 | } |
| 230 | if (!freopen("/dev/null", "w", stdout)) { | 272 | if (!freopen("/dev/null", "w", stdout)) { |
| 231 | usbmuxd_log(LL_ERROR, "ERROR: redirection of stdout failed."); | 273 | usbmuxd_log(LL_FATAL, "Redirection of stdout failed."); |
| 274 | return -3; | ||
| 275 | } | ||
| 276 | |||
| 277 | return 0; | ||
| 278 | } | ||
| 279 | |||
| 280 | static int notify_parent(int status) | ||
| 281 | { | ||
| 282 | int res; | ||
| 283 | |||
| 284 | report_to_parent = 0; | ||
| 285 | if ((res = write(daemon_pipe, &status, sizeof(int))) != sizeof(int)) { | ||
| 286 | usbmuxd_log(LL_FATAL, "Could not notify parent!"); | ||
| 287 | if(res >= 0) | ||
| 288 | return -2; | ||
| 289 | else | ||
| 290 | return res; | ||
| 232 | } | 291 | } |
| 292 | close(daemon_pipe); | ||
| 233 | if (!freopen("/dev/null", "w", stderr)) { | 293 | if (!freopen("/dev/null", "w", stderr)) { |
| 234 | usbmuxd_log(LL_ERROR, "ERROR: redirection of stderr failed."); | 294 | usbmuxd_log(LL_FATAL, "Redirection of stderr failed."); |
| 295 | return -1; | ||
| 235 | } | 296 | } |
| 236 | |||
| 237 | return 0; | 297 | return 0; |
| 238 | } | 298 | } |
| 239 | 299 | ||
| @@ -310,8 +370,9 @@ int main(int argc, char *argv[]) | |||
| 310 | { | 370 | { |
| 311 | int listenfd; | 371 | int listenfd; |
| 312 | int res = 0; | 372 | int res = 0; |
| 313 | FILE *lfd = NULL; | 373 | int lfd; |
| 314 | struct flock lock; | 374 | struct flock lock; |
| 375 | char pids[10]; | ||
| 315 | 376 | ||
| 316 | parse_opts(argc, argv); | 377 | parse_opts(argc, argv); |
| 317 | 378 | ||
| @@ -333,60 +394,77 @@ int main(int argc, char *argv[]) | |||
| 333 | 394 | ||
| 334 | set_signal_handlers(); | 395 | set_signal_handlers(); |
| 335 | 396 | ||
| 336 | lfd = fopen(lockfile, "r"); | 397 | res = lfd = open(lockfile, O_WRONLY|O_CREAT, 0644); |
| 337 | if (lfd) { | 398 | if(res == -1) { |
| 338 | lock.l_type = 0; | 399 | usbmuxd_log(LL_FATAL, "Could not open lockfile"); |
| 339 | lock.l_whence = SEEK_SET; | 400 | goto terminate; |
| 340 | lock.l_start = 0; | 401 | } |
| 341 | lock.l_len = 0; | 402 | lock.l_type = F_WRLCK; |
| 342 | fcntl(fileno(lfd), F_GETLK, &lock); | 403 | lock.l_whence = SEEK_SET; |
| 343 | fclose(lfd); | 404 | lock.l_start = 0; |
| 344 | if (lock.l_type != F_UNLCK) { | 405 | lock.l_len = 0; |
| 345 | if (opt_exit) { | 406 | fcntl(lfd, F_GETLK, &lock); |
| 346 | if (lock.l_pid && !kill(lock.l_pid, 0)) { | 407 | close(lfd); |
| 347 | usbmuxd_log(LL_NOTICE, "sending signal %d to instance with pid %d", exit_signal, lock.l_pid); | 408 | if (lock.l_type != F_UNLCK) { |
| 348 | if (kill(lock.l_pid, exit_signal) < 0) { | 409 | if (opt_exit) { |
| 349 | usbmuxd_log(LL_FATAL, "Error: could not deliver signal %d to pid %d", exit_signal, lock.l_pid); | 410 | if (lock.l_pid && !kill(lock.l_pid, 0)) { |
| 350 | } | 411 | usbmuxd_log(LL_NOTICE, "Sending signal %d to instance with pid %d", exit_signal, lock.l_pid); |
| 351 | res = 0; | 412 | res = 0; |
| 352 | goto terminate; | 413 | if (kill(lock.l_pid, exit_signal) < 0) { |
| 353 | } else { | 414 | usbmuxd_log(LL_FATAL, "Could not deliver signal %d to pid %d", exit_signal, lock.l_pid); |
| 354 | usbmuxd_log(LL_ERROR, "Could not determine pid of the other running instance!"); | ||
| 355 | res = -1; | 415 | res = -1; |
| 356 | goto terminate; | ||
| 357 | } | 416 | } |
| 417 | goto terminate; | ||
| 358 | } else { | 418 | } else { |
| 359 | if (!opt_udev) { | 419 | usbmuxd_log(LL_ERROR, "Could not determine pid of the other running instance!"); |
| 360 | usbmuxd_log(LL_ERROR, "Another instance is already running (pid %d). exiting.", lock.l_pid); | 420 | res = -1; |
| 361 | res = -1; | ||
| 362 | } else { | ||
| 363 | usbmuxd_log(LL_NOTICE, "Another instance is already running (pid %d). exiting.", lock.l_pid); | ||
| 364 | res = 0; | ||
| 365 | } | ||
| 366 | goto terminate; | 421 | goto terminate; |
| 367 | } | 422 | } |
| 423 | } else { | ||
| 424 | if (!opt_udev) { | ||
| 425 | usbmuxd_log(LL_ERROR, "Another instance is already running (pid %d). exiting.", lock.l_pid); | ||
| 426 | res = -1; | ||
| 427 | } else { | ||
| 428 | usbmuxd_log(LL_NOTICE, "Another instance is already running (pid %d). exiting.", lock.l_pid); | ||
| 429 | res = 0; | ||
| 430 | } | ||
| 431 | goto terminate; | ||
| 368 | } | 432 | } |
| 369 | } | 433 | } |
| 434 | unlink(lockfile); | ||
| 370 | 435 | ||
| 371 | if (opt_exit) { | 436 | if (opt_exit) { |
| 372 | usbmuxd_log(LL_NOTICE, "No running instance found, none killed. exiting."); | 437 | usbmuxd_log(LL_NOTICE, "No running instance found, none killed. exiting."); |
| 373 | goto terminate; | 438 | goto terminate; |
| 374 | } | 439 | } |
| 375 | 440 | ||
| 376 | // now open the lockfile and place the lock | 441 | if (!foreground) { |
| 377 | lfd = fopen(lockfile, "w"); | 442 | if ((res = daemonize()) < 0) { |
| 378 | if (lfd) { | 443 | fprintf(stderr, "usbmuxd: FATAL: Could not daemonize!\n"); |
| 379 | lock.l_type = F_WRLCK; | 444 | usbmuxd_log(LL_FATAL, "Could not daemonize!"); |
| 380 | lock.l_whence = SEEK_SET; | ||
| 381 | lock.l_start = 0; | ||
| 382 | lock.l_len = 0; | ||
| 383 | if ((res = fcntl(fileno(lfd), F_SETLK, &lock)) < 0) { | ||
| 384 | usbmuxd_log(LL_FATAL, "Lockfile locking failed!"); | ||
| 385 | goto terminate; | 445 | goto terminate; |
| 386 | } | 446 | } |
| 387 | } else { | 447 | } |
| 388 | usbmuxd_log(LL_FATAL, "Lockfile open failed!"); | 448 | |
| 389 | res = -1; | 449 | // now open the lockfile and place the lock |
| 450 | res = lfd = open(lockfile, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644); | ||
| 451 | if(res < 0) { | ||
| 452 | usbmuxd_log(LL_FATAL, "Could not open lockfile"); | ||
| 453 | goto terminate; | ||
| 454 | } | ||
| 455 | lock.l_type = F_WRLCK; | ||
| 456 | lock.l_whence = SEEK_SET; | ||
| 457 | lock.l_start = 0; | ||
| 458 | lock.l_len = 0; | ||
| 459 | if ((res = fcntl(lfd, F_SETLK, &lock)) < 0) { | ||
| 460 | usbmuxd_log(LL_FATAL, "Lockfile locking failed!"); | ||
| 461 | goto terminate; | ||
| 462 | } | ||
| 463 | sprintf(pids, "%d", getpid()); | ||
| 464 | if ((res = write(lfd, pids, strlen(pids))) != strlen(pids)) { | ||
| 465 | usbmuxd_log(LL_FATAL, "Could not write pidfile!"); | ||
| 466 | if(res >= 0) | ||
| 467 | res = -2; | ||
| 390 | goto terminate; | 468 | goto terminate; |
| 391 | } | 469 | } |
| 392 | 470 | ||
| @@ -400,7 +478,7 @@ int main(int argc, char *argv[]) | |||
| 400 | struct passwd *pw = getpwnam(drop_user); | 478 | struct passwd *pw = getpwnam(drop_user); |
| 401 | if (!pw) { | 479 | if (!pw) { |
| 402 | usbmuxd_log(LL_FATAL, "Dropping privileges failed, check if user '%s' exists!", drop_user); | 480 | usbmuxd_log(LL_FATAL, "Dropping privileges failed, check if user '%s' exists!", drop_user); |
| 403 | res = 1; | 481 | res = -1; |
| 404 | goto terminate; | 482 | goto terminate; |
| 405 | } | 483 | } |
| 406 | 484 | ||
| @@ -420,12 +498,12 @@ int main(int argc, char *argv[]) | |||
| 420 | // security check | 498 | // security check |
| 421 | if (setuid(0) != -1) { | 499 | if (setuid(0) != -1) { |
| 422 | usbmuxd_log(LL_FATAL, "Failed to drop privileges properly!"); | 500 | usbmuxd_log(LL_FATAL, "Failed to drop privileges properly!"); |
| 423 | res = 1; | 501 | res = -1; |
| 424 | goto terminate; | 502 | goto terminate; |
| 425 | } | 503 | } |
| 426 | if (getuid() != pw->pw_uid || getgid() != pw->pw_gid) { | 504 | if (getuid() != pw->pw_uid || getgid() != pw->pw_gid) { |
| 427 | usbmuxd_log(LL_FATAL, "Failed to drop privileges properly!"); | 505 | usbmuxd_log(LL_FATAL, "Failed to drop privileges properly!"); |
| 428 | res = 1; | 506 | res = -1; |
| 429 | goto terminate; | 507 | goto terminate; |
| 430 | } | 508 | } |
| 431 | usbmuxd_log(LL_NOTICE, "Successfully dropped privileges to '%s'", drop_user); | 509 | usbmuxd_log(LL_NOTICE, "Successfully dropped privileges to '%s'", drop_user); |
| @@ -441,13 +519,9 @@ int main(int argc, char *argv[]) | |||
| 441 | 519 | ||
| 442 | usbmuxd_log(LL_NOTICE, "Initialization complete"); | 520 | usbmuxd_log(LL_NOTICE, "Initialization complete"); |
| 443 | 521 | ||
| 444 | if (!foreground) { | 522 | if (report_to_parent) |
| 445 | if ((res = daemonize()) < 0) { | 523 | if((res = notify_parent(0)) < 0) |
| 446 | fprintf(stderr, "usbmuxd: FATAL: Could not daemonize!\n"); | ||
| 447 | usbmuxd_log(LL_FATAL, "Could not daemonize!"); | ||
| 448 | goto terminate; | 524 | goto terminate; |
| 449 | } | ||
| 450 | } | ||
| 451 | 525 | ||
| 452 | res = main_loop(listenfd); | 526 | res = main_loop(listenfd); |
| 453 | if(res < 0) | 527 | if(res < 0) |
| @@ -463,7 +537,12 @@ int main(int argc, char *argv[]) | |||
| 463 | terminate: | 537 | terminate: |
| 464 | log_disable_syslog(); | 538 | log_disable_syslog(); |
| 465 | 539 | ||
| 466 | if(res < 0) | 540 | if (res < 0) |
| 467 | return -res; | 541 | res = -res; |
| 468 | return 0; | 542 | else |
| 543 | res = 0; | ||
| 544 | if (report_to_parent) | ||
| 545 | notify_parent(res); | ||
| 546 | |||
| 547 | return res; | ||
| 469 | } | 548 | } |
