URI:
       tdaemonize.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tdaemonize.c (3190B)
       ---
            1 #include <u.h>
            2 #include <sys/time.h>
            3 #include <sys/resource.h>
            4 #include "threadimpl.h"
            5 
            6 #undef waitpid
            7 #undef pipe
            8 #undef wait
            9 
           10 static int sigpid;
           11 static int threadpassfd = -1;
           12 static int gotsigchld;
           13 
           14 static void
           15 child(void)
           16 {
           17         int status, pid;
           18         struct rlimit rl;
           19 
           20         notedisable("sys: child");
           21         pid = waitpid(sigpid, &status, 0);
           22         if(pid < 0){
           23                 fprint(2, "%s: wait: %r\n", argv0);
           24                 _exit(97);
           25         }
           26         if(WIFEXITED(status))
           27                  _exit(WEXITSTATUS(status));
           28         if(WIFSIGNALED(status)){
           29                 /*
           30                  * Make sure we don't scribble over the nice
           31                  * core file that our child just wrote out.
           32                  */
           33                 rl.rlim_cur = 0;
           34                 rl.rlim_max = 0;
           35                 setrlimit(RLIMIT_CORE, &rl);
           36 
           37                 signal(WTERMSIG(status), SIG_DFL);
           38                 raise(WTERMSIG(status));
           39                 _exit(98);        /* not reached */
           40         }
           41         if(WIFSTOPPED(status)){
           42                 fprint(2, "%s: wait pid %d stopped\n", argv0, pid);
           43                 return;
           44         }
           45 #ifdef WIFCONTINUED
           46         if(WIFCONTINUED(status)){
           47                 fprint(2, "%s: wait pid %d continued\n", argv0, pid);
           48                 return;
           49         }
           50 #endif
           51         fprint(2, "%s: wait pid %d status 0x%ux\n", argv0, pid, status);
           52         _exit(99);
           53 }
           54 
           55 static void
           56 sigpass(int sig)
           57 {
           58         if(sigpid == 1){
           59                 gotsigchld = 1;
           60                 return;
           61         }
           62 
           63         if(sig == SIGCHLD)
           64                 child();
           65         else
           66                 kill(sigpid, sig);
           67 }
           68 
           69 static int sigs[] =
           70 {
           71         SIGHUP, SIGINT, SIGQUIT, SIGILL,
           72         SIGTRAP, SIGABRT, SIGBUS, SIGFPE,
           73         SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE,
           74         SIGALRM, SIGTERM, SIGCHLD, SIGSTOP,
           75         /*SIGTSTP, SIGTTIN, SIGTTOU,*/ SIGURG,
           76         SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF,
           77 #ifdef SIGWINCH
           78         SIGWINCH,
           79 #endif
           80 #ifdef SIGIO
           81         SIGIO,
           82 #endif
           83 #ifdef SIGEMT
           84         SIGEMT,
           85 #endif
           86 #ifdef SIGPWR
           87         SIGPWR,
           88 #endif
           89 #ifdef SIGINFO
           90         SIGINFO,
           91 #endif
           92         SIGSYS
           93 };
           94 
           95 void
           96 _threadsetupdaemonize(void)
           97 {
           98         int i, n, pid;
           99         int p[2];
          100         char buf[20];
          101 
          102         sigpid = 1;
          103 
          104         /*
          105          * We've been told this program is likely to background itself.
          106          * Put it in its own process group so that we don't get a SIGHUP
          107          * when the parent exits.
          108          */
          109         setpgid(0, 0);
          110 
          111         if(pipe(p) < 0)
          112                 sysfatal("passer pipe: %r");
          113 
          114         /* hide these somewhere they won't cause harm */
          115         /* can't go too high: NetBSD max is 64, for example */
          116         if(dup(p[0], 28) < 0 || dup(p[1], 29) < 0)
          117                 sysfatal("passer pipe dup: %r");
          118         close(p[0]);
          119         close(p[1]);
          120         p[0] = 28;
          121         p[1] = 29;
          122 
          123         /* close on exec */
          124         if(fcntl(p[0], F_SETFD, 1) < 0 || fcntl(p[1], F_SETFD, 1) < 0)
          125                 sysfatal("passer pipe pipe fcntl: %r");
          126 
          127         noteenable("sys: child");
          128         signal(SIGCHLD, sigpass);
          129         switch(pid = fork()){
          130         case -1:
          131                 sysfatal("passer fork: %r");
          132         default:
          133                 close(p[1]);
          134                 break;
          135         case 0:
          136                 notedisable("sys: child");
          137                 signal(SIGCHLD, SIG_DFL);
          138         /*        rfork(RFNOTEG); */
          139                 close(p[0]);
          140                 threadpassfd = p[1];
          141                 return;
          142         }
          143 
          144         sigpid = pid;
          145         if(gotsigchld)
          146                 sigpass(SIGCHLD);
          147 
          148         for(i=0; i<nelem(sigs); i++){
          149                 struct sigaction sa;
          150 
          151                 memset(&sa, 0, sizeof sa);
          152                 sa.sa_handler = sigpass;
          153                 sa.sa_flags |= SA_RESTART;
          154                 sigaction(sigs[i], &sa, nil);
          155         }
          156 
          157         for(;;){
          158                 n = read(p[0], buf, sizeof buf-1);
          159                 if(n == 0){        /* program exited */
          160                         child();
          161                 }
          162                 if(n > 0)
          163                         break;
          164                 print("passer read: %r\n");
          165         }
          166         buf[n] = 0;
          167         _exit(atoi(buf));
          168 }
          169 
          170 void
          171 _threaddaemonize(void)
          172 {
          173         if(threadpassfd < 0)
          174                 sysfatal("threads in main proc exited w/o threadmaybackground");
          175         write(threadpassfd, "0", 1);
          176         close(threadpassfd);
          177         threadpassfd = -1;
          178 }