tdaemonize.c - plan9port - [fork] Plan 9 from user space
git clone git://src.adamsgaard.dk/plan9port
Log
Files
Refs
README
LICENSE
---
tdaemonize.c (3190B)
---
     1 #include 
     2 #include 
     3 #include 
     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 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 }