tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Library support for two-phase daemonization



Anthony Mallet wrote:
> More details: I've seen this pattern in X.org (IIRC) and I'm using this 
> without
> any issue so far:
> 
>   /* daemonize */
>   if (daemonize) {
>     switch(fork()) {
>       case -1:
>         perror("cannot fork");
>         exit(2);
> 
>       case 0: /* child */ {
>         int fd;
> 
>         if (setsid() == -1) exit(-1);
>         if (chdir("/")) /*noop*/;
> 
>         fd = open("/dev/null", O_RDWR, 0);
>         if (fd != -1) {
>           (void)dup2(fd, STDIN_FILENO);
>           if (fd > STDERR_FILENO)
>             (void)close(fd);
>         }
>         signal(SIGUSR1, SIG_IGN);
>       }

Missing a "break;" here?

>       default: /* parent */ {
>         sigset_t sset;
>         int sig = 0;
> 
>         sigemptyset(&sset);
>         sigaddset(&sset, SIGUSR1);
>         sigprocmask(SIG_BLOCK, &sset, NULL);
>         do { sigwait(&sset, &sig); } while (sig == 0);
>         assert(sig == SIGUSR1);
>         _exit(0);
>       }
>     }
>   }
> 
>   handler = signal(SIGUSR1, SIG_IGN);
>   /* if SIGUSR1 is set to SIG_IGN, it was either set above or inherited from
>    *  the parent (because we did not fiddle with signal handlers in the child
>    *  yet). So either:
>    *   - the parent really ignores it
>    *   - the parent is in the 'parent' branch above
>    */
> 
>   /* do initialization stuff etc ... then signal the parent */
> 
>   if (handler == SIG_IGN)
>     kill(getppid(), SIGUSR1);

I think this suffers from a similar race condition as Iain's code; 
the SIGUSR1 may be delivered to the parent before it has called
sigprocmask().
-- 
Andreas Gustafsson, gson%gson.org@localhost


Home | Main Index | Thread Index | Old Index