Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/runit/runsv.c
- Timestamp:
- Feb 25, 2011, 9:26:54 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.9/mindi-busybox/runit/runsv.c
r1765 r2725 26 26 */ 27 27 28 /* Busyboxed by Den is Vlasenko <vda.linux@googlemail.com> */28 /* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */ 29 29 /* TODO: depends on runit_lib.c - review and reduce/eliminate */ 30 30 … … 61 61 /* Compare possibly overflowing unsigned counters */ 62 62 #define LESS(a,b) ((int)((unsigned)(b) - (unsigned)(a)) > 0) 63 64 static int selfpipe[2];65 63 66 64 /* state */ … … 81 79 smallint state; 82 80 smallint ctrl; 83 smallint want;81 smallint sd_want; 84 82 smallint islog; 85 83 struct timespec start; … … 87 85 int fdcontrol; 88 86 int fdcontrolwrite; 87 int wstat; 89 88 }; 90 89 91 static struct svdir svd[2]; 92 static smallint sigterm; 93 static smallint haslog; 94 static smallint pidchanged = 1; 95 static int logpipe[2]; 96 static char *dir; 90 struct globals { 91 smallint haslog; 92 smallint sigterm; 93 smallint pidchanged; 94 struct fd_pair selfpipe; 95 struct fd_pair logpipe; 96 char *dir; 97 struct svdir svd[2]; 98 } FIX_ALIASING; 99 #define G (*(struct globals*)&bb_common_bufsiz1) 100 #define haslog (G.haslog ) 101 #define sigterm (G.sigterm ) 102 #define pidchanged (G.pidchanged ) 103 #define selfpipe (G.selfpipe ) 104 #define logpipe (G.logpipe ) 105 #define dir (G.dir ) 106 #define svd (G.svd ) 107 #define INIT_G() do { \ 108 pidchanged = 1; \ 109 } while (0) 97 110 98 111 static void fatal2_cannot(const char *m1, const char *m2) … … 116 129 } 117 130 118 static void s_child(int sig_no )119 { 120 write(selfpipe [1], "", 1);121 } 122 123 static void s_term(int sig_no )131 static void s_child(int sig_no UNUSED_PARAM) 132 { 133 write(selfpipe.wr, "", 1); 134 } 135 136 static void s_term(int sig_no UNUSED_PARAM) 124 137 { 125 138 sigterm = 1; 126 write(selfpipe[1], "", 1); /* XXX */ 127 } 128 129 static char *add_str(char *p, const char *to_add) 139 write(selfpipe.wr, "", 1); /* XXX */ 140 } 141 142 /* libbb candidate */ 143 static char *bb_stpcpy(char *p, const char *to_add) 130 144 { 131 145 while ((*p = *to_add) != '\0') { … … 138 152 static int open_trunc_or_warn(const char *name) 139 153 { 140 int fd = open_trunc(name); 154 /* Why O_NDELAY? */ 155 int fd = open(name, O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT, 0644); 141 156 if (fd < 0) 142 157 bb_perror_msg("%s: warning: cannot open %s", 143 158 dir, name); 144 159 return fd; 145 }146 147 static int rename_or_warn(const char *old, const char *new)148 {149 if (rename(old, new) == -1) {150 bb_perror_msg("%s: warning: cannot rename %s to %s",151 dir, old, new);152 return -1;153 }154 return 0;155 160 } 156 161 … … 188 193 switch (s->state) { 189 194 case S_DOWN: 190 p = add_str(p, "down");195 p = bb_stpcpy(p, "down"); 191 196 break; 192 197 case S_RUN: 193 p = add_str(p, "run");198 p = bb_stpcpy(p, "run"); 194 199 break; 195 200 case S_FINISH: 196 p = add_str(p, "finish");201 p = bb_stpcpy(p, "finish"); 197 202 break; 198 203 } 199 if (s->ctrl & C_PAUSE) p = add_str(p, ", paused"); 200 if (s->ctrl & C_TERM) p = add_str(p, ", got TERM"); 204 if (s->ctrl & C_PAUSE) 205 p = bb_stpcpy(p, ", paused"); 206 if (s->ctrl & C_TERM) 207 p = bb_stpcpy(p, ", got TERM"); 201 208 if (s->state != S_DOWN) 202 switch (s-> want) {209 switch (s->sd_want) { 203 210 case W_DOWN: 204 p = add_str(p, ", want down");211 p = bb_stpcpy(p, ", want down"); 205 212 break; 206 213 case W_EXIT: 207 p = add_str(p, ", want exit");214 p = bb_stpcpy(p, ", want exit"); 208 215 break; 209 216 } … … 223 230 if (s->ctrl & C_PAUSE) 224 231 status.paused = 1; 225 if (s-> want == W_UP)232 if (s->sd_want == W_UP) 226 233 status.want = 'u'; 227 234 else … … 246 253 static unsigned custom(struct svdir *s, char c) 247 254 { 248 int pid;255 pid_t pid; 249 256 int w; 250 257 char a[10]; 251 258 struct stat st; 252 char *prog[2]; 253 254 if (s->islog)return 0;259 260 if (s->islog) 261 return 0; 255 262 strcpy(a, "control/?"); 256 a[8] = c; 263 a[8] = c; /* replace '?' */ 257 264 if (stat(a, &st) == 0) { 258 265 if (st.st_mode & S_IXUSR) { 259 pid = fork();266 pid = vfork(); 260 267 if (pid == -1) { 261 warn_cannot(" fork for control/?");268 warn_cannot("vfork for control/?"); 262 269 return 0; 263 270 } 264 if (!pid) { 265 if (haslog && dup2(logpipe[1], 1) == -1) 271 if (pid == 0) { 272 /* child */ 273 if (haslog && dup2(logpipe.wr, 1) == -1) 266 274 warn_cannot("setup stdout for control/?"); 267 prog[0] = a; 268 prog[1] = NULL; 269 execve(a, prog, environ); 275 execl(a, a, (char *) NULL); 270 276 fatal_cannot("run control/?"); 271 277 } 272 while (wait_pid(&w, pid) == -1) {273 if (errno == EINTR) continue;278 /* parent */ 279 if (safe_waitpid(pid, &w, 0) == -1) { 274 280 warn_cannot("wait for child control/?"); 275 281 return 0; 276 282 } 277 return !wait_exitcode(w);283 return WEXITSTATUS(w) == 0; 278 284 } 279 285 } else { … … 291 297 update_status(s); 292 298 } 293 if (s-> want == W_DOWN) {299 if (s->sd_want == W_DOWN) { 294 300 kill(s->pid, SIGCONT); 295 301 custom(s, 'd'); 296 302 return; 297 303 } 298 if (s-> want == W_EXIT) {304 if (s->sd_want == W_EXIT) { 299 305 kill(s->pid, SIGCONT); 300 306 custom(s, 'x'); … … 305 311 { 306 312 int p; 307 char *run[2]; 308 309 if (s->state == S_FINISH) 310 run[0] = (char*)"./finish"; 311 else { 312 run[0] = (char*)"./run"; 313 const char *arg[4]; 314 char exitcode[sizeof(int)*3 + 2]; 315 316 if (s->state == S_FINISH) { 317 /* Two arguments are given to ./finish. The first one is ./run exit code, 318 * or -1 if ./run didnt exit normally. The second one is 319 * the least significant byte of the exit status as determined by waitpid; 320 * for instance it is 0 if ./run exited normally, and the signal number 321 * if ./run was terminated by a signal. If runsv cannot start ./run 322 * for some reason, the exit code is 111 and the status is 0. 323 */ 324 arg[0] = "./finish"; 325 arg[1] = "-1"; 326 if (WIFEXITED(s->wstat)) { 327 *utoa_to_buf(WEXITSTATUS(s->wstat), exitcode, sizeof(exitcode)) = '\0'; 328 arg[1] = exitcode; 329 } 330 //arg[2] = "0"; 331 //if (WIFSIGNALED(s->wstat)) { 332 arg[2] = utoa(WTERMSIG(s->wstat)); 333 //} 334 arg[3] = NULL; 335 } else { 336 arg[0] = "./run"; 337 arg[1] = NULL; 313 338 custom(s, 'u'); 314 339 } 315 run[1] = NULL;316 340 317 341 if (s->pid != 0) 318 342 stopservice(s); /* should never happen */ 319 while ((p = fork()) == -1) {320 warn_cannot(" fork, sleeping");343 while ((p = vfork()) == -1) { 344 warn_cannot("vfork, sleeping"); 321 345 sleep(5); 322 346 } … … 324 348 /* child */ 325 349 if (haslog) { 350 /* NB: bug alert! right order is close, then dup2 */ 326 351 if (s->islog) { 327 xdup2(logpipe[0], 0);328 close(logpipe[1]);329 352 xchdir("./log"); 353 close(logpipe.wr); 354 xdup2(logpipe.rd, 0); 330 355 } else { 331 xdup2(logpipe[1], 1); 332 close(logpipe[0]); 333 } 334 } 335 signal(SIGCHLD, SIG_DFL); 336 signal(SIGTERM, SIG_DFL); 356 close(logpipe.rd); 357 xdup2(logpipe.wr, 1); 358 } 359 } 360 /* Non-ignored signals revert to SIG_DFL on exec anyway */ 361 /*bb_signals(0 362 + (1 << SIGCHLD) 363 + (1 << SIGTERM) 364 , SIG_DFL);*/ 337 365 sig_unblock(SIGCHLD); 338 366 sig_unblock(SIGTERM); 339 execvp(*run, run); 340 fatal2_cannot(s->islog ? "start log/" : "start ", *run); 341 } 367 execv(arg[0], (char**) arg); 368 fatal2_cannot(s->islog ? "start log/" : "start ", arg[0]); 369 } 370 /* parent */ 342 371 if (s->state != S_FINISH) { 343 372 gettimeofday_ns(&s->start); … … 356 385 switch (c) { 357 386 case 'd': /* down */ 358 s-> want = W_DOWN;387 s->sd_want = W_DOWN; 359 388 update_status(s); 360 389 if (s->pid && s->state != S_FINISH) … … 362 391 break; 363 392 case 'u': /* up */ 364 s-> want = W_UP;393 s->sd_want = W_UP; 365 394 update_status(s); 366 395 if (s->pid == 0) … … 370 399 if (s->islog) 371 400 break; 372 s-> want = W_EXIT;401 s->sd_want = W_EXIT; 373 402 update_status(s); 374 403 /* FALLTHROUGH */ … … 391 420 if (s->pid && !custom(s, c)) 392 421 kill(s->pid, SIGCONT); 393 if (s->ctrl & C_PAUSE) 394 s->ctrl &= ~C_PAUSE; 422 s->ctrl &= ~C_PAUSE; 395 423 update_status(s); 396 424 break; 397 425 case 'o': /* once */ 398 s-> want = W_DOWN;426 s->sd_want = W_DOWN; 399 427 update_status(s); 400 428 if (!s->pid) … … 427 455 } 428 456 429 int runsv_main(int argc, char **argv) ;430 int runsv_main(int argc , char **argv)457 int runsv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 458 int runsv_main(int argc UNUSED_PARAM, char **argv) 431 459 { 432 460 struct stat s; … … 435 463 char buf[256]; 436 464 437 if (!argv[1] || argv[2])438 bb_show_usage(); 439 dir = argv[1];440 441 xpipe (selfpipe);442 c oe(selfpipe[0]);443 c oe(selfpipe[1]);444 ndelay_on(selfpipe [0]);445 ndelay_on(selfpipe [1]);465 INIT_G(); 466 467 dir = single_argv(argv); 468 469 xpiped_pair(selfpipe); 470 close_on_exec_on(selfpipe.rd); 471 close_on_exec_on(selfpipe.wr); 472 ndelay_on(selfpipe.rd); 473 ndelay_on(selfpipe.wr); 446 474 447 475 sig_block(SIGCHLD); 448 sig_catch(SIGCHLD, s_child);476 bb_signals_recursive_norestart(1 << SIGCHLD, s_child); 449 477 sig_block(SIGTERM); 450 sig_catch(SIGTERM, s_term);478 bb_signals_recursive_norestart(1 << SIGTERM, s_term); 451 479 452 480 xchdir(dir); … … 454 482 if (S_DOWN) svd[0].state = S_DOWN; /* otherwise already 0 (bss) */ 455 483 if (C_NOOP) svd[0].ctrl = C_NOOP; 456 if (W_UP) svd[0]. want = W_UP;484 if (W_UP) svd[0].sd_want = W_UP; 457 485 /* bss: svd[0].islog = 0; */ 458 486 /* bss: svd[1].pid = 0; */ 459 487 gettimeofday_ns(&svd[0].start); 460 if (stat("down", &s) != -1) svd[0].want = W_DOWN; 488 if (stat("down", &s) != -1) 489 svd[0].sd_want = W_DOWN; 461 490 462 491 if (stat("log", &s) == -1) { … … 471 500 svd[1].state = S_DOWN; 472 501 svd[1].ctrl = C_NOOP; 473 svd[1]. want = W_UP;502 svd[1].sd_want = W_UP; 474 503 svd[1].islog = 1; 475 504 gettimeofday_ns(&svd[1].start); 476 505 if (stat("log/down", &s) != -1) 477 svd[1]. want = W_DOWN;478 xpipe (logpipe);479 c oe(logpipe[0]);480 c oe(logpipe[1]);506 svd[1].sd_want = W_DOWN; 507 xpiped_pair(logpipe); 508 close_on_exec_on(logpipe.rd); 509 close_on_exec_on(logpipe.wr); 481 510 } 482 511 } … … 496 525 svd[0].fdlock = xopen3("log/supervise/lock"+4, 497 526 O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600); 498 if ( lock_exnb(svd[0].fdlock) == -1)527 if (flock(svd[0].fdlock, LOCK_EX | LOCK_NB) == -1) 499 528 fatal_cannot("lock supervise/lock"); 500 c oe(svd[0].fdlock);529 close_on_exec_on(svd[0].fdlock); 501 530 if (haslog) { 502 531 if (mkdir("log/supervise", 0700) == -1) { … … 520 549 svd[1].fdlock = xopen3("log/supervise/lock", 521 550 O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600); 522 if ( lock_ex(svd[1].fdlock) == -1)551 if (flock(svd[1].fdlock, LOCK_EX) == -1) 523 552 fatal_cannot("lock log/supervise/lock"); 524 c oe(svd[1].fdlock);553 close_on_exec_on(svd[1].fdlock); 525 554 } 526 555 527 556 mkfifo("log/supervise/control"+4, 0600); 528 557 svd[0].fdcontrol = xopen("log/supervise/control"+4, O_RDONLY|O_NDELAY); 529 c oe(svd[0].fdcontrol);558 close_on_exec_on(svd[0].fdcontrol); 530 559 svd[0].fdcontrolwrite = xopen("log/supervise/control"+4, O_WRONLY|O_NDELAY); 531 c oe(svd[0].fdcontrolwrite);560 close_on_exec_on(svd[0].fdcontrolwrite); 532 561 update_status(&svd[0]); 533 562 if (haslog) { 534 563 mkfifo("log/supervise/control", 0600); 535 564 svd[1].fdcontrol = xopen("log/supervise/control", O_RDONLY|O_NDELAY); 536 c oe(svd[1].fdcontrol);565 close_on_exec_on(svd[1].fdcontrol); 537 566 svd[1].fdcontrolwrite = xopen("log/supervise/control", O_WRONLY|O_NDELAY); 538 c oe(svd[1].fdcontrolwrite);567 close_on_exec_on(svd[1].fdcontrolwrite); 539 568 update_status(&svd[1]); 540 569 } 541 570 mkfifo("log/supervise/ok"+4, 0600); 542 571 fd = xopen("log/supervise/ok"+4, O_RDONLY|O_NDELAY); 543 c oe(fd);572 close_on_exec_on(fd); 544 573 if (haslog) { 545 574 mkfifo("log/supervise/ok", 0600); 546 575 fd = xopen("log/supervise/ok", O_RDONLY|O_NDELAY); 547 c oe(fd);576 close_on_exec_on(fd); 548 577 } 549 578 for (;;) { … … 553 582 554 583 if (haslog) 555 if (!svd[1].pid && svd[1]. want == W_UP)584 if (!svd[1].pid && svd[1].sd_want == W_UP) 556 585 startservice(&svd[1]); 557 586 if (!svd[0].pid) 558 if (svd[0]. want == W_UP || svd[0].state == S_FINISH)587 if (svd[0].sd_want == W_UP || svd[0].state == S_FINISH) 559 588 startservice(&svd[0]); 560 589 561 x[0].fd = selfpipe [0];590 x[0].fd = selfpipe.rd; 562 591 x[0].events = POLLIN; 563 592 x[1].fd = svd[0].fdcontrol; … … 572 601 sig_block(SIGCHLD); 573 602 574 while (read(selfpipe [0], &ch, 1) == 1)603 while (read(selfpipe.rd, &ch, 1) == 1) 575 604 continue; 576 605 577 606 for (;;) { 578 int child;607 pid_t child; 579 608 int wstat; 580 609 581 child = wait_ nohang(&wstat);610 child = wait_any_nohang(&wstat); 582 611 if (!child) 583 612 break; … … 585 614 break; 586 615 if (child == svd[0].pid) { 616 svd[0].wstat = wstat; 587 617 svd[0].pid = 0; 588 618 pidchanged = 1; 589 svd[0].ctrl &= ~C_TERM;619 svd[0].ctrl &= ~C_TERM; 590 620 if (svd[0].state != S_FINISH) { 591 fd = open _read("finish");621 fd = open("finish", O_RDONLY|O_NDELAY); 592 622 if (fd != -1) { 593 623 close(fd); … … 606 636 if (haslog) { 607 637 if (child == svd[1].pid) { 638 svd[0].wstat = wstat; 608 639 svd[1].pid = 0; 609 640 pidchanged = 1; … … 617 648 } 618 649 } 619 } 650 } /* for (;;) */ 620 651 if (read(svd[0].fdcontrol, &ch, 1) == 1) 621 652 ctrl(&svd[0], ch); … … 629 660 } 630 661 631 if (svd[0]. want == W_EXIT && svd[0].state == S_DOWN) {662 if (svd[0].sd_want == W_EXIT && svd[0].state == S_DOWN) { 632 663 if (svd[1].pid == 0) 633 _exit( 0);634 if (svd[1]. want != W_EXIT) {635 svd[1]. want = W_EXIT;664 _exit(EXIT_SUCCESS); 665 if (svd[1].sd_want != W_EXIT) { 666 svd[1].sd_want = W_EXIT; 636 667 /* stopservice(&svd[1]); */ 637 668 update_status(&svd[1]); 638 close(logpipe [1]);639 close(logpipe [0]);640 } 641 } 642 } 669 close(logpipe.wr); 670 close(logpipe.rd); 671 } 672 } 673 } /* for (;;) */ 643 674 /* not reached */ 644 675 return 0;
Note:
See TracChangeset
for help on using the changeset viewer.