serva.c (18670B)
1 /* serva: a simple service supervisor */ 2 3 #ifndef _XOPEN_SOURCE 4 #define _XOPEN_SOURCE 700 5 #endif 6 7 #include "util.h" 8 9 #include <dirent.h> 10 #include <errno.h> 11 #include <fcntl.h> 12 #include <limits.h> 13 #include <poll.h> 14 #include <signal.h> 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <string.h> 18 #include <sys/socket.h> 19 #include <sys/stat.h> 20 #include <sys/types.h> 21 #include <sys/un.h> 22 #include <sys/wait.h> 23 #include <time.h> 24 #include <unistd.h> 25 26 #ifndef SVC_DIR 27 #define SVC_DIR "/etc/ssv" 28 #endif 29 #ifndef SOCK_PATH 30 #define SOCK_PATH "/run/serva.sock" 31 #endif 32 #define MAX_SVCS 256 33 #define MAX_BACKOFF 60 34 #define MAX_DEPS 16 35 #define MAX_DEPNAME 64 36 37 struct Service { 38 char stage[NAME_MAX]; 39 char name[NAME_MAX]; 40 char dir[PATH_MAX]; 41 char arg[NAME_MAX]; 42 pid_t pid; 43 pid_t logpid; 44 int pipefd[2]; 45 time_t last_start; 46 time_t next_restart; 47 int backoff; 48 unsigned long nruns; 49 int last_exit; 50 int last_sig; 51 int want_up; 52 int noreset; 53 int once; 54 int down; 55 int has_logger; 56 char need[MAX_DEPS][MAX_DEPNAME]; 57 int nneed; 58 char after[MAX_DEPS][MAX_DEPNAME]; 59 int nafter; 60 }; 61 62 static struct Service svcs[MAX_SVCS]; 63 static size_t nsvcs; 64 static int sigpipe[2]; 65 static volatile sig_atomic_t got_term; 66 67 static void 68 cloexec(int fd) 69 { 70 int flags; 71 72 flags = fcntl(fd, F_GETFD); 73 if (flags < 0 || fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) 74 eprintf("fcntl FD_CLOEXEC:"); 75 } 76 77 static void 78 sleep_briefly(void) 79 { 80 struct timespec delay = { 0, 100000000L }; 81 82 while (nanosleep(&delay, &delay) < 0 && errno == EINTR) 83 ; 84 } 85 86 /* signal handler: wake self-pipe on SIGCHLD, flag SIGTERM */ 87 static void 88 signal_handler(int sig) 89 { 90 char c; 91 int saved_errno = errno; 92 93 if (sig == SIGTERM) 94 got_term = 1; 95 c = 0; 96 write(sigpipe[1], &c, 1); 97 errno = saved_errno; 98 } 99 100 /* parse @-templates: "tty@tty1" -> arg "tty1" */ 101 static void 102 parse_arg(const char *name, char *arg) 103 { 104 const char *at; 105 106 at = strchr(name, '@'); 107 if (at) 108 strlcpy(arg, at + 1, NAME_MAX); 109 else 110 arg[0] = '\0'; 111 } 112 113 /* has_file: check if <dir>/<name> exists */ 114 static int 115 has_file(const char *dir, const char *name) 116 { 117 char path[PATH_MAX]; 118 119 snprintf(path, sizeof(path), "%s/%s", dir, name); 120 return access(path, F_OK) == 0; 121 } 122 123 /* svc_cmp: sort by (stage, name) */ 124 static int 125 svc_cmp(const void *a, const void *b) 126 { 127 const struct Service *sa = a, *sb = b; 128 int c; 129 130 c = strcmp(sa->stage, sb->stage); 131 if (c != 0) 132 return c; 133 return strcmp(sa->name, sb->name); 134 } 135 136 /* endswith_at: true if name ends with '@' (template dir) */ 137 static int 138 endswith_at(const char *name) 139 { 140 size_t len; 141 142 len = strlen(name); 143 return len > 0 && name[len - 1] == '@'; 144 } 145 146 /* find_service: lookup by "name" or "stage/name" */ 147 static struct Service * 148 find_service(const char *id) 149 { 150 size_t i; 151 const char *slash; 152 char stage[NAME_MAX]; 153 154 slash = strchr(id, '/'); 155 if (slash) { 156 size_t len; 157 158 len = slash - id; 159 if (len >= NAME_MAX) 160 return NULL; 161 memcpy(stage, id, len); 162 stage[len] = '\0'; 163 for (i = 0; i < nsvcs; i++) 164 if (strcmp(svcs[i].stage, stage) == 0 165 && strcmp(svcs[i].name, slash + 1) == 0) 166 return &svcs[i]; 167 } else { 168 for (i = 0; i < nsvcs; i++) 169 if (strcmp(svcs[i].name, id) == 0) 170 return &svcs[i]; 171 } 172 return NULL; 173 } 174 175 /* deps_met: true if all need-deps are running */ 176 static int 177 deps_met(struct Service *s) 178 { 179 int i; 180 struct Service *dep; 181 182 for (i = 0; i < s->nneed; i++) { 183 dep = find_service(s->need[i]); 184 if (!dep || dep->pid <= 0) 185 return 0; 186 } 187 return 1; 188 } 189 190 /* has_after: true if s has after-hint for name */ 191 static int 192 has_after(struct Service *s, const char *name) 193 { 194 int i; 195 196 for (i = 0; i < s->nafter; i++) 197 if (strcmp(s->after[i], name) == 0) 198 return 1; 199 return 0; 200 } 201 202 /* adjust_after_order: swap services so after-hints are respected 203 within each stage. */ 204 static void 205 adjust_after_order(void) 206 { 207 int swapped; 208 size_t i, j; 209 struct Service tmp; 210 211 do { 212 swapped = 0; 213 for (i = 0; i < nsvcs; i++) { 214 for (j = i + 1; j < nsvcs; j++) { 215 if (strcmp(svcs[i].stage, svcs[j].stage) != 0) 216 continue; 217 if (has_after(&svcs[i], svcs[j].name)) { 218 tmp = svcs[i]; 219 svcs[i] = svcs[j]; 220 svcs[j] = tmp; 221 swapped = 1; 222 } 223 } 224 } 225 } while (swapped); 226 } 227 228 /* scan_deps: read need/ and after/ directories into service struct */ 229 static void 230 scan_deps(struct Service *s) 231 { 232 DIR *d; 233 struct dirent *e; 234 char path[PATH_MAX]; 235 236 snprintf(path, sizeof(path), "%s/need", s->dir); 237 d = opendir(path); 238 if (d) { 239 while ((e = readdir(d)) != NULL && s->nneed < MAX_DEPS) { 240 if (e->d_name[0] == '.') 241 continue; 242 strlcpy(s->need[s->nneed], e->d_name, MAX_DEPNAME); 243 s->nneed++; 244 } 245 closedir(d); 246 } 247 248 snprintf(path, sizeof(path), "%s/after", s->dir); 249 d = opendir(path); 250 if (d) { 251 while ((e = readdir(d)) != NULL && s->nafter < MAX_DEPS) { 252 if (e->d_name[0] == '.') 253 continue; 254 strlcpy(s->after[s->nafter], e->d_name, MAX_DEPNAME); 255 s->nafter++; 256 } 257 closedir(d); 258 } 259 } 260 261 static void 262 scan_services(void) 263 { 264 DIR *d, *sd; 265 struct dirent *e, *se; 266 char stagepath[PATH_MAX], svcpath[PATH_MAX], tmp[PATH_MAX]; 267 struct stat st, sst; 268 269 d = opendir(SVC_DIR); 270 if (!d) 271 eprintf("opendir %s:", SVC_DIR); 272 273 nsvcs = 0; 274 while ((e = readdir(d)) != NULL && nsvcs < MAX_SVCS) { 275 if (e->d_name[0] == '.') 276 continue; 277 278 snprintf(stagepath, sizeof(stagepath), "%s/%s", 279 SVC_DIR, e->d_name); 280 if (stat(stagepath, &st) < 0) 281 continue; 282 if (!S_ISDIR(st.st_mode)) 283 continue; 284 285 /* scan services within this stage */ 286 sd = opendir(stagepath); 287 if (!sd) 288 continue; 289 while ((se = readdir(sd)) != NULL && nsvcs < MAX_SVCS) { 290 struct Service *s; 291 292 if (se->d_name[0] == '.') 293 continue; 294 if (endswith_at(se->d_name)) 295 continue; 296 297 if (snprintf(svcpath, sizeof(svcpath), "%s/%s", 298 stagepath, se->d_name) >= (int)sizeof(svcpath)) 299 continue; 300 if (stat(svcpath, &sst) < 0) 301 continue; 302 if (!S_ISDIR(sst.st_mode)) 303 continue; 304 305 /* run is required */ 306 if (snprintf(tmp, sizeof(tmp), "%s/run", svcpath) >= (int)sizeof(tmp)) 307 continue; 308 if (access(tmp, X_OK) < 0) 309 continue; 310 311 s = &svcs[nsvcs]; 312 memset(s, 0, sizeof(*s)); 313 strlcpy(s->stage, e->d_name, NAME_MAX); 314 strlcpy(s->name, se->d_name, NAME_MAX); 315 316 if (!realpath(svcpath, s->dir)) 317 strlcpy(s->dir, svcpath, PATH_MAX); 318 319 parse_arg(s->name, s->arg); 320 321 snprintf(tmp, sizeof(tmp), "%s/log", s->dir); 322 s->has_logger = (access(tmp, X_OK) == 0); 323 324 s->noreset = has_file(s->dir, "noreset"); 325 s->once = has_file(s->dir, "once"); 326 s->down = has_file(s->dir, "down"); 327 328 scan_deps(s); 329 330 s->pipefd[0] = -1; 331 s->pipefd[1] = -1; 332 nsvcs++; 333 } 334 closedir(sd); 335 } 336 closedir(d); 337 338 qsort(svcs, nsvcs, sizeof(*svcs), svc_cmp); 339 adjust_after_order(); 340 } 341 342 static void 343 start_service(struct Service *s) 344 { 345 char runpath[PATH_MAX], logpath[PATH_MAX]; 346 char *argv[3]; 347 pid_t pid; 348 349 if (s->pid > 0) 350 return; 351 352 if (snprintf(runpath, sizeof(runpath), "%s/run", s->dir) >= (int)sizeof(runpath) || 353 snprintf(logpath, sizeof(logpath), "%s/log", s->dir) >= (int)sizeof(logpath)) { 354 weprintf("path too long: %s", s->dir); 355 return; 356 } 357 358 /* create logging pipe if needed */ 359 if (s->has_logger && s->pipefd[0] < 0) { 360 if (pipe(s->pipefd) < 0) { 361 weprintf("pipe:"); 362 return; 363 } 364 cloexec(s->pipefd[0]); 365 cloexec(s->pipefd[1]); 366 } 367 368 s->last_start = time(NULL); 369 s->last_exit = -1; 370 s->last_sig = 0; 371 372 /* fork service process */ 373 pid = fork(); 374 if (pid < 0) { 375 weprintf("fork:"); 376 return; 377 } 378 if (pid == 0) { 379 sigset_t empty; 380 381 sigemptyset(&empty); 382 sigprocmask(SIG_SETMASK, &empty, NULL); 383 signal(SIGPIPE, SIG_DFL); 384 setsid(); 385 386 if (chdir(s->dir) < 0) 387 eprintf("chdir %s:", s->dir); 388 389 if (s->pipefd[1] >= 0) { 390 dup2(s->pipefd[1], STDOUT_FILENO); 391 dup2(s->pipefd[1], STDERR_FILENO); 392 if (s->pipefd[1] > STDERR_FILENO) 393 close(s->pipefd[1]); 394 close(s->pipefd[0]); 395 } 396 397 setenv("SVC_NAME", s->name, 1); 398 setenv("SVC_STAGE", s->stage, 1); 399 if (s->arg[0]) 400 setenv("SVC_ARG", s->arg, 1); 401 402 argv[0] = "run"; 403 argv[1] = s->arg[0] ? s->arg : NULL; 404 argv[2] = NULL; 405 406 execv(runpath, argv); 407 eprintf("exec %s:", runpath); 408 } 409 s->pid = pid; 410 s->nruns++; 411 412 /* fork logger process if pipe was created */ 413 if (s->pipefd[0] >= 0) { 414 pid = fork(); 415 if (pid < 0) { 416 weprintf("fork logger:"); 417 } else if (pid == 0) { 418 sigset_t empty; 419 420 sigemptyset(&empty); 421 sigprocmask(SIG_SETMASK, &empty, NULL); 422 signal(SIGPIPE, SIG_DFL); 423 424 if (chdir(s->dir) < 0) 425 eprintf("chdir %s:", s->dir); 426 427 dup2(s->pipefd[0], STDIN_FILENO); 428 if (s->pipefd[0] > STDIN_FILENO) 429 close(s->pipefd[0]); 430 close(s->pipefd[1]); 431 432 setenv("SVC_NAME", s->name, 1); 433 setenv("SVC_STAGE", s->stage, 1); 434 if (s->arg[0]) 435 setenv("SVC_ARG", s->arg, 1); 436 437 execl(logpath, "log", NULL); 438 eprintf("exec %s:", logpath); 439 } 440 s->logpid = pid; 441 442 /* serva closes both pipe ends */ 443 close(s->pipefd[0]); 444 close(s->pipefd[1]); 445 s->pipefd[0] = -1; 446 s->pipefd[1] = -1; 447 } 448 } 449 450 static void 451 stop_service(struct Service *s) 452 { 453 int i; 454 455 if (s->pid > 0) { 456 kill(s->pid, SIGTERM); 457 for (i = 0; i < 50; i++) { 458 if (waitpid(s->pid, NULL, WNOHANG) > 0) 459 break; 460 if (i == 40) 461 kill(s->pid, SIGKILL); 462 sleep_briefly(); 463 } 464 s->pid = 0; 465 } 466 if (s->logpid > 0) { 467 kill(s->logpid, SIGTERM); 468 waitpid(s->logpid, NULL, 0); 469 s->logpid = 0; 470 } 471 s->want_up = 0; 472 s->next_restart = 0; 473 s->backoff = 0; 474 } 475 476 /* stop_for_dep: stop but keep want_up - waiting for dependency */ 477 static void 478 stop_for_dep(struct Service *s) 479 { 480 int i; 481 482 if (s->pid > 0) { 483 kill(s->pid, SIGTERM); 484 for (i = 0; i < 50; i++) { 485 if (waitpid(s->pid, NULL, WNOHANG) > 0) 486 break; 487 if (i == 40) 488 kill(s->pid, SIGKILL); 489 sleep_briefly(); 490 } 491 s->pid = 0; 492 } 493 if (s->logpid > 0) { 494 kill(s->logpid, SIGTERM); 495 waitpid(s->logpid, NULL, 0); 496 s->logpid = 0; 497 } 498 s->next_restart = 0; 499 s->backoff = 0; 500 /* want_up stays 1 - will restart when deps are met */ 501 } 502 503 static void 504 restart_service(struct Service *s) 505 { 506 stop_service(s); 507 s->want_up = 1; 508 start_service(s); 509 } 510 511 /* stop_cascade: stop all services whose need-deps are not running. */ 512 static void 513 stop_cascade(void) 514 { 515 size_t i; 516 int j, found; 517 518 do { 519 found = 0; 520 for (i = 0; i < nsvcs; i++) { 521 struct Service *s = &svcs[i]; 522 523 if (s->pid <= 0 || !s->want_up) 524 continue; 525 for (j = 0; j < s->nneed; j++) { 526 struct Service *dep; 527 528 dep = find_service(s->need[j]); 529 if (!dep || dep->pid <= 0) { 530 stop_for_dep(s); 531 found = 1; 532 break; 533 } 534 } 535 } 536 } while (found); 537 } 538 539 static void 540 handle_child(pid_t pid, int status) 541 { 542 size_t i; 543 time_t now; 544 545 now = time(NULL); 546 for (i = 0; i < nsvcs; i++) { 547 struct Service *s = &svcs[i]; 548 549 if (s->pid == pid) { 550 s->pid = 0; 551 if (WIFEXITED(status)) 552 s->last_exit = WEXITSTATUS(status); 553 else if (WIFSIGNALED(status)) 554 s->last_sig = WTERMSIG(status); 555 /* kill logger too - pipe is broken */ 556 if (s->logpid > 0) { 557 kill(s->logpid, SIGTERM); 558 waitpid(s->logpid, NULL, 0); 559 s->logpid = 0; 560 } 561 562 /* cascade-stop services that need this one */ 563 stop_cascade(); 564 565 if (!s->want_up) 566 return; 567 if (s->once || s->noreset) { 568 /* don't restart - clear want_up so check_restart skips */ 569 s->want_up = 0; 570 return; 571 } 572 if (now - s->last_start < 60) 573 s->backoff = MIN(s->backoff + 1, MAX_BACKOFF); 574 else 575 s->backoff = 1; 576 s->next_restart = now + s->backoff; 577 return; 578 } 579 if (s->logpid == pid) { 580 s->logpid = 0; 581 /* logger died: restart whole service for clean pipe */ 582 if (s->want_up && s->pid > 0) 583 restart_service(s); 584 return; 585 } 586 } 587 } 588 589 static void 590 reap_all(void) 591 { 592 pid_t pid; 593 int status; 594 595 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) 596 handle_child(pid, status); 597 } 598 599 /* check_restarts: start services that are ready (deps met, backoff 600 expired). */ 601 static void 602 check_restarts(void) 603 { 604 size_t i; 605 time_t now; 606 int progress; 607 608 now = time(NULL); 609 do { 610 progress = 0; 611 for (i = 0; i < nsvcs; i++) { 612 struct Service *s = &svcs[i]; 613 614 if (!s->want_up || s->pid > 0 || s->down) 615 continue; 616 if (!deps_met(s)) 617 continue; 618 if (s->next_restart > 0 && now < s->next_restart) 619 continue; 620 s->next_restart = 0; 621 s->backoff = 0; 622 start_service(s); 623 if (s->pid > 0) 624 progress = 1; 625 } 626 } while (progress); 627 } 628 629 static int 630 compute_timeout(void) 631 { 632 size_t i; 633 time_t now, min, wait; 634 635 now = time(NULL); 636 min = 0; 637 for (i = 0; i < nsvcs; i++) { 638 struct Service *s = &svcs[i]; 639 640 if (!s->want_up || s->pid > 0 || s->next_restart == 0) 641 continue; 642 if (!deps_met(s)) 643 continue; 644 wait = s->next_restart - now; 645 if (wait <= 0) 646 return 0; 647 if (min == 0 || wait < min) 648 min = wait; 649 } 650 if (min == 0) 651 return -1; 652 return (int)(min * 1000); 653 } 654 655 /* status_str: human-readable service state */ 656 static const char * 657 status_str(struct Service *s) 658 { 659 if (s->down) 660 return "DOWN*"; 661 if (s->pid > 0) 662 return "RUN"; 663 if (s->want_up && !deps_met(s)) 664 return "WAIT*"; 665 if (s->want_up) 666 return "WAIT"; 667 if (s->once) 668 return "DONE"; 669 return "DOWN"; 670 } 671 672 /* format_status: write one service's status to the control stream */ 673 static void 674 format_status(struct Service *s, FILE *out) 675 { 676 char full[2 * NAME_MAX + 2]; 677 int j; 678 679 snprintf(full, sizeof(full), "%s/%s", s->stage, s->name); 680 fprintf(out, 681 "%-32s %s%s pid=%ld runs=%lu uptime=%lds", 682 full, 683 status_str(s), 684 s->noreset ? " (noreset)" : "", 685 (long)s->pid, 686 s->nruns, 687 s->pid > 0 ? (long)(time(NULL) - s->last_start) : 0L); 688 if (s->last_exit >= 0) 689 fprintf(out, " exit=%d", s->last_exit); 690 if (s->last_sig > 0) 691 fprintf(out, " sig=%d", s->last_sig); 692 if (s->nneed > 0) { 693 fprintf(out, " need="); 694 for (j = 0; j < s->nneed; j++) 695 fprintf(out, "%s%s", 696 j ? "," : "", s->need[j]); 697 } 698 if (s->nafter > 0) { 699 fprintf(out, " after="); 700 for (j = 0; j < s->nafter; j++) 701 fprintf(out, "%s%s", 702 j ? "," : "", s->after[j]); 703 } 704 fputc('\n', out); 705 } 706 707 /* handle_conn: process one control connection */ 708 static void 709 handle_conn(int conn) 710 { 711 char buf[4096], cmd, *name, *p; 712 ssize_t n; 713 size_t i; 714 struct Service *s; 715 FILE *out; 716 717 n = read(conn, buf, sizeof(buf) - 1); 718 if (n <= 0) { 719 close(conn); 720 return; 721 } 722 buf[n] = '\0'; 723 out = fdopen(conn, "w"); 724 if (!out) { 725 weprintf("fdopen:"); 726 close(conn); 727 return; 728 } 729 730 p = strchr(buf, '\n'); 731 if (p) 732 *p = '\0'; 733 734 cmd = buf[0]; 735 name = (buf[1] == ' ') ? buf + 2 : buf + 1; 736 737 switch (cmd) { 738 case 'u': 739 if (strcmp(name, "a") == 0) { 740 for (i = 0; i < nsvcs; i++) { 741 if (svcs[i].down) 742 continue; 743 svcs[i].want_up = 1; 744 } 745 check_restarts(); 746 fprintf(out, "OK: started all\n"); 747 } else { 748 s = find_service(name); 749 if (!s) { 750 fprintf(out, "ERR: no such service: %s\n", name); 751 break; 752 } 753 /* explicit svc -u overrides down and deps */ 754 s->down = 0; 755 s->want_up = 1; 756 s->next_restart = 0; 757 s->backoff = 0; 758 start_service(s); 759 fprintf(out, "OK: %s up\n", name); 760 } 761 break; 762 case 'd': 763 if (strcmp(name, "a") == 0) { 764 for (i = 0; i < nsvcs; i++) 765 stop_service(&svcs[i]); 766 fprintf(out, "OK: stopped all\n"); 767 } else { 768 s = find_service(name); 769 if (!s) { 770 fprintf(out, "ERR: no such service: %s\n", name); 771 break; 772 } 773 stop_service(s); 774 fprintf(out, "OK: %s down\n", name); 775 } 776 stop_cascade(); 777 break; 778 case 'r': 779 s = find_service(name); 780 if (!s) { 781 fprintf(out, "ERR: no such service: %s\n", name); 782 break; 783 } 784 restart_service(s); 785 fprintf(out, "OK: %s restarted\n", name); 786 break; 787 case 'k': 788 s = find_service(name); 789 if (!s) { 790 fprintf(out, "ERR: no such service: %s\n", name); 791 break; 792 } 793 if (s->pid > 0) 794 kill(s->pid, SIGKILL); 795 fprintf(out, "OK: %s killed\n", name); 796 break; 797 case 't': 798 s = find_service(name); 799 if (!s) { 800 fprintf(out, "ERR: no such service: %s\n", name); 801 break; 802 } 803 if (s->pid > 0) 804 kill(s->pid, SIGTERM); 805 fprintf(out, "OK: %s terminated\n", name); 806 break; 807 case 's': 808 if (name[0]) { 809 s = find_service(name); 810 if (!s) { 811 fprintf(out, "ERR: no such service: %s\n", name); 812 break; 813 } 814 format_status(s, out); 815 break; 816 } 817 for (i = 0; i < nsvcs && !ferror(out); i++) 818 format_status(&svcs[i], out); 819 break; 820 default: 821 fprintf(out, "ERR: unknown command\n"); 822 break; 823 } 824 825 fshut(out, SOCK_PATH); 826 } 827 828 static void 829 shutdown_serva(void) 830 { 831 size_t i; 832 833 for (i = 0; i < nsvcs; i++) 834 stop_service(&svcs[i]); 835 unlink(SOCK_PATH); 836 } 837 838 int 839 main(void) 840 { 841 int sock, nfds, timeout, conn; 842 struct sockaddr_un addr; 843 struct pollfd pfds[2]; 844 struct sigaction sa; 845 mode_t mask; 846 char c; 847 size_t i; 848 849 /* self-pipe for signal integration with poll */ 850 if (pipe(sigpipe) < 0) 851 eprintf("pipe:"); 852 cloexec(sigpipe[0]); 853 cloexec(sigpipe[1]); 854 if (fcntl(sigpipe[0], F_SETFL, O_NONBLOCK) < 0 || 855 fcntl(sigpipe[1], F_SETFL, O_NONBLOCK) < 0) 856 eprintf("fcntl O_NONBLOCK:"); 857 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) 858 eprintf("signal SIGPIPE:"); 859 860 /* install signal handlers */ 861 memset(&sa, 0, sizeof(sa)); 862 sa.sa_handler = signal_handler; 863 sigemptyset(&sa.sa_mask); 864 sa.sa_flags = SA_RESTART; 865 sigaction(SIGCHLD, &sa, NULL); 866 sigaction(SIGTERM, &sa, NULL); 867 868 scan_services(); 869 870 /* create control socket */ 871 sock = socket(AF_UNIX, SOCK_STREAM, 0); 872 if (sock < 0) 873 eprintf("socket:"); 874 cloexec(sock); 875 memset(&addr, 0, sizeof(addr)); 876 addr.sun_family = AF_UNIX; 877 if (strlcpy(addr.sun_path, SOCK_PATH, sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) 878 eprintf("socket path too long: %s\n", SOCK_PATH); 879 unlink(SOCK_PATH); 880 mask = umask(0077); 881 if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) 882 eprintf("bind %s:", SOCK_PATH); 883 umask(mask); 884 if (chmod(SOCK_PATH, 0600) < 0) 885 eprintf("chmod %s:", SOCK_PATH); 886 if (listen(sock, 16) < 0) 887 eprintf("listen:"); 888 889 /* mark all non-down services as wanting to be up */ 890 for (i = 0; i < nsvcs; i++) { 891 if (svcs[i].down) 892 continue; 893 svcs[i].want_up = 1; 894 } 895 896 /* start services whose deps are met */ 897 check_restarts(); 898 899 /* warn about services stuck on unmet deps */ 900 for (i = 0; i < nsvcs; i++) { 901 if (svcs[i].want_up && svcs[i].pid == 0 902 && !svcs[i].down && !deps_met(&svcs[i])) 903 weprintf("unmet dependency for %s/%s", 904 svcs[i].stage, svcs[i].name); 905 } 906 907 /* main loop */ 908 for (;;) { 909 timeout = compute_timeout(); 910 911 pfds[0].fd = sock; 912 pfds[0].events = POLLIN; 913 pfds[1].fd = sigpipe[0]; 914 pfds[1].events = POLLIN; 915 916 nfds = poll(pfds, 2, timeout); 917 if (nfds < 0) { 918 if (errno == EINTR) 919 continue; 920 eprintf("poll:"); 921 } 922 923 if (pfds[0].revents & POLLIN) { 924 conn = accept(sock, NULL, NULL); 925 if (conn >= 0) { 926 cloexec(conn); 927 handle_conn(conn); 928 } 929 } 930 931 if (pfds[1].revents & POLLIN) { 932 while (read(sigpipe[0], &c, 1) > 0) 933 ; 934 reap_all(); 935 } 936 937 if (got_term) 938 break; 939 940 check_restarts(); 941 } 942 943 shutdown_serva(); 944 return 0; 945 }