Search code examples
clinuxforksystems-programming

Creating daemon process in UNIX enviroment


I have picked the following example from APUE :

void daemonize(const char* cmd)
{
        int i,fd0,fd1,fd2;
        pid_t pid;
        struct rlimit r1;
        struct sigaction sa;

        //clear all file masks
        umask(0);

        //get max number of file descriptors
        if(getrlimit(RLIMIT_NOFILE,&r1) < 0)
        {
                perror("error getting file descriptor size");
                return;
        }

        //become a session leader
        if((pid = fork()) < 0)
        {
                perror("error forking");
                return;
        }
        else if(pid == 0)
        {
                setsid();
        }
        else
        {
                exit(0); //parent exits
        }

        sa.sa_handler = SIG_IGN;
        sigemptyset(&sa.sa_mask);
        sa.sa_flags = 0;
        if(sigaction(SIGHUP,&sa,NULL) < 0)
        {
                return;
        }

        if((pid = fork()) < 0)
        {
                return;
        }
        else if(pid != 0)
        {
                exit(0); //parent
        }

        //child continues

        syslog(LOG_ERR,"chile continuing with pid : %d",getpid());
        //change the working directory
        if(chdir("/") < 0)
        {
                return;
        }

        if(r1.rlim_max == RLIM_INFINITY)
                r1.rlim_max = 1024;
        for(i=0;i<r1.rlim_max;i++)
                close(i);

        //attach the file descriptors to /dev/null
        fd0 = open("/dev/null",O_RDWR);
        fd1 = dup(0);
        fd2 = dup(0);

        //initialize the log file
        openlog(cmd, LOG_CONS,LOG_DAEMON);
        if(fd0!=0 || fd1!=1 || fd2!=2)
        {
                syslog(LOG_ERR,"unexpected file descriptors %d %d %d\n",fd0,fd1,fd2);
                exit(1);
        }
}


int main()
{
        daemonize("date");
        pause();    //how is this working???
}

What I don't understand is how the pause() from the main function is working? What I was expecting is that since we have done exit(0) for the parent process in daemonize(), it should have exited and resulted in the normal termination of the main() process. It should have never returned to the main() and the call to pause() should not even happen. Why it did not terminate and why the pause() got called?


Solution

  • The code forks twice, producing a parent, a child, and a grandchild. The first two each exit(0); the last returns from daemonize.