Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/runit/runsv.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 983 by niro, Fri Apr 24 18:33:46 2009 UTC revision 984 by niro, Sun May 30 11:32:42 2010 UTC
# Line 78  struct svdir { Line 78  struct svdir {
78   int pid;   int pid;
79   smallint state;   smallint state;
80   smallint ctrl;   smallint ctrl;
81   smallint want;   smallint sd_want;
82   smallint islog;   smallint islog;
83   struct timespec start;   struct timespec start;
84   int fdlock;   int fdlock;
85   int fdcontrol;   int fdcontrol;
86   int fdcontrolwrite;   int fdcontrolwrite;
87     int wstat;
88  };  };
89    
90  struct globals {  struct globals {
# Line 138  static void s_term(int sig_no UNUSED_PAR Line 139  static void s_term(int sig_no UNUSED_PAR
139   write(selfpipe.wr, "", 1); /* XXX */   write(selfpipe.wr, "", 1); /* XXX */
140  }  }
141    
142  static char *add_str(char *p, const char *to_add)  /* libbb candidate */
143    static char *bb_stpcpy(char *p, const char *to_add)
144  {  {
145   while ((*p = *to_add) != '\0') {   while ((*p = *to_add) != '\0') {
146   p++;   p++;
# Line 189  static void update_status(struct svdir * Line 191  static void update_status(struct svdir *
191   char *p = stat_buf;   char *p = stat_buf;
192   switch (s->state) {   switch (s->state) {
193   case S_DOWN:   case S_DOWN:
194   p = add_str(p, "down");   p = bb_stpcpy(p, "down");
195   break;   break;
196   case S_RUN:   case S_RUN:
197   p = add_str(p, "run");   p = bb_stpcpy(p, "run");
198   break;   break;
199   case S_FINISH:   case S_FINISH:
200   p = add_str(p, "finish");   p = bb_stpcpy(p, "finish");
201   break;   break;
202   }   }
203   if (s->ctrl & C_PAUSE) p = add_str(p, ", paused");   if (s->ctrl & C_PAUSE)
204   if (s->ctrl & C_TERM) p = add_str(p, ", got TERM");   p = bb_stpcpy(p, ", paused");
205     if (s->ctrl & C_TERM)
206     p = bb_stpcpy(p, ", got TERM");
207   if (s->state != S_DOWN)   if (s->state != S_DOWN)
208   switch (s->want) {   switch (s->sd_want) {
209   case W_DOWN:   case W_DOWN:
210   p = add_str(p, ", want down");   p = bb_stpcpy(p, ", want down");
211   break;   break;
212   case W_EXIT:   case W_EXIT:
213   p = add_str(p, ", want exit");   p = bb_stpcpy(p, ", want exit");
214   break;   break;
215   }   }
216   *p++ = '\n';   *p++ = '\n';
# Line 224  static void update_status(struct svdir * Line 228  static void update_status(struct svdir *
228   status.pid_le32 = SWAP_LE32(s->pid);   status.pid_le32 = SWAP_LE32(s->pid);
229   if (s->ctrl & C_PAUSE)   if (s->ctrl & C_PAUSE)
230   status.paused = 1;   status.paused = 1;
231   if (s->want == W_UP)   if (s->sd_want == W_UP)
232   status.want = 'u';   status.want = 'u';
233   else   else
234   status.want = 'd';   status.want = 'd';
# Line 251  static unsigned custom(struct svdir *s, Line 255  static unsigned custom(struct svdir *s,
255   int w;   int w;
256   char a[10];   char a[10];
257   struct stat st;   struct stat st;
  char *prog[2];  
258    
259   if (s->islog) return 0;   if (s->islog)
260     return 0;
261   strcpy(a, "control/?");   strcpy(a, "control/?");
262   a[8] = c; /* replace '?' */   a[8] = c; /* replace '?' */
263   if (stat(a, &st) == 0) {   if (stat(a, &st) == 0) {
# Line 263  static unsigned custom(struct svdir *s, Line 267  static unsigned custom(struct svdir *s,
267   warn_cannot("vfork for control/?");   warn_cannot("vfork for control/?");
268   return 0;   return 0;
269   }   }
270   if (!pid) {   if (pid == 0) {
271   /* child */   /* child */
272   if (haslog && dup2(logpipe.wr, 1) == -1)   if (haslog && dup2(logpipe.wr, 1) == -1)
273   warn_cannot("setup stdout for control/?");   warn_cannot("setup stdout for control/?");
274   prog[0] = a;   execl(a, a, (char *) NULL);
  prog[1] = NULL;  
  execv(a, prog);  
275   fatal_cannot("run control/?");   fatal_cannot("run control/?");
276   }   }
277   /* parent */   /* parent */
278   while (safe_waitpid(pid, &w, 0) == -1) {   if (safe_waitpid(pid, &w, 0) == -1) {
279   warn_cannot("wait for child control/?");   warn_cannot("wait for child control/?");
280   return 0;   return 0;
281   }   }
282   return !wait_exitcode(w);   return WEXITSTATUS(w) == 0;
283   }   }
284   } else {   } else {
285   if (errno != ENOENT)   if (errno != ENOENT)
# Line 293  static void stopservice(struct svdir *s) Line 295  static void stopservice(struct svdir *s)
295   s->ctrl |= C_TERM;   s->ctrl |= C_TERM;
296   update_status(s);   update_status(s);
297   }   }
298   if (s->want == W_DOWN) {   if (s->sd_want == W_DOWN) {
299   kill(s->pid, SIGCONT);   kill(s->pid, SIGCONT);
300   custom(s, 'd');   custom(s, 'd');
301   return;   return;
302   }   }
303   if (s->want == W_EXIT) {   if (s->sd_want == W_EXIT) {
304   kill(s->pid, SIGCONT);   kill(s->pid, SIGCONT);
305   custom(s, 'x');   custom(s, 'x');
306   }   }
# Line 307  static void stopservice(struct svdir *s) Line 309  static void stopservice(struct svdir *s)
309  static void startservice(struct svdir *s)  static void startservice(struct svdir *s)
310  {  {
311   int p;   int p;
312   char *run[2];   const char *arg[4];
313     char exitcode[sizeof(int)*3 + 2];
314    
315   if (s->state == S_FINISH)   if (s->state == S_FINISH) {
316   run[0] = (char*)"./finish";  /* Two arguments are given to ./finish. The first one is ./run exit code,
317   else {   * or -1 if ./run didnt exit normally. The second one is
318   run[0] = (char*)"./run";   * the least significant byte of the exit status as determined by waitpid;
319     * for instance it is 0 if ./run exited normally, and the signal number
320     * if ./run was terminated by a signal. If runsv cannot start ./run
321     * for some reason, the exit code is 111 and the status is 0.
322     */
323     arg[0] = "./finish";
324     arg[1] = "-1";
325     if (WIFEXITED(s->wstat)) {
326     *utoa_to_buf(WEXITSTATUS(s->wstat), exitcode, sizeof(exitcode)) = '\0';
327     arg[1] = exitcode;
328     }
329     //arg[2] = "0";
330     //if (WIFSIGNALED(s->wstat)) {
331     arg[2] = utoa(WTERMSIG(s->wstat));
332     //}
333     arg[3] = NULL;
334     } else {
335     arg[0] = "./run";
336     arg[1] = NULL;
337   custom(s, 'u');   custom(s, 'u');
338   }   }
  run[1] = NULL;  
339    
340   if (s->pid != 0)   if (s->pid != 0)
341   stopservice(s); /* should never happen */   stopservice(s); /* should never happen */
# Line 343  static void startservice(struct svdir *s Line 363  static void startservice(struct svdir *s
363   , SIG_DFL);*/   , SIG_DFL);*/
364   sig_unblock(SIGCHLD);   sig_unblock(SIGCHLD);
365   sig_unblock(SIGTERM);   sig_unblock(SIGTERM);
366   execvp(*run, run);   execv(arg[0], (char**) arg);
367   fatal2_cannot(s->islog ? "start log/" : "start ", *run);   fatal2_cannot(s->islog ? "start log/" : "start ", arg[0]);
368   }   }
369   /* parent */   /* parent */
370   if (s->state != S_FINISH) {   if (s->state != S_FINISH) {
# Line 363  static int ctrl(struct svdir *s, char c) Line 383  static int ctrl(struct svdir *s, char c)
383    
384   switch (c) {   switch (c) {
385   case 'd': /* down */   case 'd': /* down */
386   s->want = W_DOWN;   s->sd_want = W_DOWN;
387   update_status(s);   update_status(s);
388   if (s->pid && s->state != S_FINISH)   if (s->pid && s->state != S_FINISH)
389   stopservice(s);   stopservice(s);
390   break;   break;
391   case 'u': /* up */   case 'u': /* up */
392   s->want = W_UP;   s->sd_want = W_UP;
393   update_status(s);   update_status(s);
394   if (s->pid == 0)   if (s->pid == 0)
395   startservice(s);   startservice(s);
# Line 377  static int ctrl(struct svdir *s, char c) Line 397  static int ctrl(struct svdir *s, char c)
397   case 'x': /* exit */   case 'x': /* exit */
398   if (s->islog)   if (s->islog)
399   break;   break;
400   s->want = W_EXIT;   s->sd_want = W_EXIT;
401   update_status(s);   update_status(s);
402   /* FALLTHROUGH */   /* FALLTHROUGH */
403   case 't': /* sig term */   case 't': /* sig term */
# Line 398  static int ctrl(struct svdir *s, char c) Line 418  static int ctrl(struct svdir *s, char c)
418   case 'c': /* sig cont */   case 'c': /* sig cont */
419   if (s->pid && !custom(s, c))   if (s->pid && !custom(s, c))
420   kill(s->pid, SIGCONT);   kill(s->pid, SIGCONT);
421   if (s->ctrl & C_PAUSE)   s->ctrl &= ~C_PAUSE;
  s->ctrl &= ~C_PAUSE;  
422   update_status(s);   update_status(s);
423   break;   break;
424   case 'o': /* once */   case 'o': /* once */
425   s->want = W_DOWN;   s->sd_want = W_DOWN;
426   update_status(s);   update_status(s);
427   if (!s->pid)   if (!s->pid)
428   startservice(s);   startservice(s);
# Line 444  int runsv_main(int argc UNUSED_PARAM, ch Line 463  int runsv_main(int argc UNUSED_PARAM, ch
463    
464   INIT_G();   INIT_G();
465    
466   if (!argv[1] || argv[2])   dir = single_argv(argv);
  bb_show_usage();  
  dir = argv[1];  
467    
468   xpiped_pair(selfpipe);   xpiped_pair(selfpipe);
469   close_on_exec_on(selfpipe.rd);   close_on_exec_on(selfpipe.rd);
# Line 455  int runsv_main(int argc UNUSED_PARAM, ch Line 472  int runsv_main(int argc UNUSED_PARAM, ch
472   ndelay_on(selfpipe.wr);   ndelay_on(selfpipe.wr);
473    
474   sig_block(SIGCHLD);   sig_block(SIGCHLD);
475   bb_signals_recursive(1 << SIGCHLD, s_child);   bb_signals_recursive_norestart(1 << SIGCHLD, s_child);
476   sig_block(SIGTERM);   sig_block(SIGTERM);
477   bb_signals_recursive(1 << SIGTERM, s_term);   bb_signals_recursive_norestart(1 << SIGTERM, s_term);
478    
479   xchdir(dir);   xchdir(dir);
480   /* bss: svd[0].pid = 0; */   /* bss: svd[0].pid = 0; */
481   if (S_DOWN) svd[0].state = S_DOWN; /* otherwise already 0 (bss) */   if (S_DOWN) svd[0].state = S_DOWN; /* otherwise already 0 (bss) */
482   if (C_NOOP) svd[0].ctrl = C_NOOP;   if (C_NOOP) svd[0].ctrl = C_NOOP;
483   if (W_UP) svd[0].want = W_UP;   if (W_UP) svd[0].sd_want = W_UP;
484   /* bss: svd[0].islog = 0; */   /* bss: svd[0].islog = 0; */
485   /* bss: svd[1].pid = 0; */   /* bss: svd[1].pid = 0; */
486   gettimeofday_ns(&svd[0].start);   gettimeofday_ns(&svd[0].start);
487   if (stat("down", &s) != -1) svd[0].want = W_DOWN;   if (stat("down", &s) != -1)
488     svd[0].sd_want = W_DOWN;
489    
490   if (stat("log", &s) == -1) {   if (stat("log", &s) == -1) {
491   if (errno != ENOENT)   if (errno != ENOENT)
# Line 480  int runsv_main(int argc UNUSED_PARAM, ch Line 498  int runsv_main(int argc UNUSED_PARAM, ch
498   haslog = 1;   haslog = 1;
499   svd[1].state = S_DOWN;   svd[1].state = S_DOWN;
500   svd[1].ctrl = C_NOOP;   svd[1].ctrl = C_NOOP;
501   svd[1].want = W_UP;   svd[1].sd_want = W_UP;
502   svd[1].islog = 1;   svd[1].islog = 1;
503   gettimeofday_ns(&svd[1].start);   gettimeofday_ns(&svd[1].start);
504   if (stat("log/down", &s) != -1)   if (stat("log/down", &s) != -1)
505   svd[1].want = W_DOWN;   svd[1].sd_want = W_DOWN;
506   xpiped_pair(logpipe);   xpiped_pair(logpipe);
507   close_on_exec_on(logpipe.rd);   close_on_exec_on(logpipe.rd);
508   close_on_exec_on(logpipe.wr);   close_on_exec_on(logpipe.wr);
# Line 562  int runsv_main(int argc UNUSED_PARAM, ch Line 580  int runsv_main(int argc UNUSED_PARAM, ch
580   char ch;   char ch;
581    
582   if (haslog)   if (haslog)
583   if (!svd[1].pid && svd[1].want == W_UP)   if (!svd[1].pid && svd[1].sd_want == W_UP)
584   startservice(&svd[1]);   startservice(&svd[1]);
585   if (!svd[0].pid)   if (!svd[0].pid)
586   if (svd[0].want == W_UP || svd[0].state == S_FINISH)   if (svd[0].sd_want == W_UP || svd[0].state == S_FINISH)
587   startservice(&svd[0]);   startservice(&svd[0]);
588    
589   x[0].fd = selfpipe.rd;   x[0].fd = selfpipe.rd;
# Line 594  int runsv_main(int argc UNUSED_PARAM, ch Line 612  int runsv_main(int argc UNUSED_PARAM, ch
612   if ((child == -1) && (errno != EINTR))   if ((child == -1) && (errno != EINTR))
613   break;   break;
614   if (child == svd[0].pid) {   if (child == svd[0].pid) {
615     svd[0].wstat = wstat;
616   svd[0].pid = 0;   svd[0].pid = 0;
617   pidchanged = 1;   pidchanged = 1;
618   svd[0].ctrl &=~ C_TERM;   svd[0].ctrl &= ~C_TERM;
619   if (svd[0].state != S_FINISH) {   if (svd[0].state != S_FINISH) {
620   fd = open_read("finish");   fd = open_read("finish");
621   if (fd != -1) {   if (fd != -1) {
# Line 615  int runsv_main(int argc UNUSED_PARAM, ch Line 634  int runsv_main(int argc UNUSED_PARAM, ch
634   }   }
635   if (haslog) {   if (haslog) {
636   if (child == svd[1].pid) {   if (child == svd[1].pid) {
637     svd[0].wstat = wstat;
638   svd[1].pid = 0;   svd[1].pid = 0;
639   pidchanged = 1;   pidchanged = 1;
640   svd[1].state = S_DOWN;   svd[1].state = S_DOWN;
# Line 638  int runsv_main(int argc UNUSED_PARAM, ch Line 658  int runsv_main(int argc UNUSED_PARAM, ch
658   sigterm = 0;   sigterm = 0;
659   }   }
660    
661   if (svd[0].want == W_EXIT && svd[0].state == S_DOWN) {   if (svd[0].sd_want == W_EXIT && svd[0].state == S_DOWN) {
662   if (svd[1].pid == 0)   if (svd[1].pid == 0)
663   _exit(EXIT_SUCCESS);   _exit(EXIT_SUCCESS);
664   if (svd[1].want != W_EXIT) {   if (svd[1].sd_want != W_EXIT) {
665   svd[1].want = W_EXIT;   svd[1].sd_want = W_EXIT;
666   /* stopservice(&svd[1]); */   /* stopservice(&svd[1]); */
667   update_status(&svd[1]);   update_status(&svd[1]);
668   close(logpipe.wr);   close(logpipe.wr);

Legend:
Removed from v.983  
changed lines
  Added in v.984