smali
smali

Reputation: 4805

fork() system call within a daemon using _exit()

There are lot of questions on fork() but I am little bit confused in this code.I am analyzing a code in c++ in that I have got this function.

int daemon(int nochdir, int noclose) 
{

  switch (fork()) 
  {
    case 0:  break;
    case -1: return -1;
    default: _exit(0);          /* exit the original process */
  }

  if (setsid() < 0)               /* shoudn't fail */
    return -1;

/* dyke out this switch if you want to acquire a control tty in */
/* the future -- not normally advisable for daemons */
  printf("Starting %s                [ OK ]\n",AGENT_NAME);

  switch (fork()) 
  {
    case 0:  break;
    case -1: return -1;
    default: _exit(0);
  }

  if (!nochdir)    
  {
    chdir("/");
  }

  if (!noclose) 
  {
    dup(0); 
    dup(1);
  }

return 0;
}

So the fork will create an exact copy of the code from where the fork() has been called. so,

  1. Is switch executed twice or once?

  2. If twice then in the switch what if the child executes first? Will it just break or go to the other statements?

  3. What If the parent executes? will the main process be terminated and child will continue?

Edit: So the switch will also run twice once with parent and once with child. and behaves on the return values.

And the final thing is, the daemon is a predefined function and it has been redefined and used like user created daemon. How it will create the daemon process and what the

`if (!nochdir)    
{
    chdir("/");
}`

and

if (!noclose) 
{
    dup(0); 
    dup(1);
}

I am calling this function like this.

if (daemon(0, 0) < 0) 
{
    printf("Starting %s                [ Failed ]\n",AGENT_NAME);
    exit(2);
}

Upvotes: 0

Views: 1003

Answers (3)

4pie0
4pie0

Reputation: 29724

Is switch executed twice or once?

It is said that fork is the function that is called once but returns twice, that is once in each process: once in parent and once in a child.

man :

On success, the PID of the child process is returned in the parent, and 0 is returned in the child. On failure, -1 is returned in the parent, no child process is created, and errno is set appropriately

It might return just once (-1): only in parent if child wasn't created. It always returns in the parent ( -1 on error, > 0 on success).

If twice then in the switch what if the child executes first? Will it just break or go to the other statements?

It is unknown whether child or parent returns first. After fork() all the memory segments are copied into child, but it continues with the correct value 0 returned from the fork(). Parent continues with pid of the child. You use return value of fork in the code to determine whether you are child or parent. Maybe this will get more clear if you write code this way

int daemon( int nochdir, int noclose) 
{

  pid_t pid;                /* to drive logic in the code */ 

  if ( ( pid = Fork()) < 0) /* fork and remember actual value returned to pid */
      return -1;

  if( pid > 0)
    _exit(0);               /* exit the original process */

  // here pid is 0, i.e. the child

What If the parent executes? will the main process be terminated and child will continue?

What if the parent exit() is called before any child instructions? Then yes, parent will terminate, child will do on its own. Both the parent and the child processes possess the same code segments, but execute independently of each other (unless you added some synchronization).

http://linux.die.net/man/2/fork

Upvotes: 3

DarkDust
DarkDust

Reputation: 92335

  1. Unless there's an error, fork will return twice: once in the parent process and once in the child process. fork creates a copy of the current process, then continues execution in both processes and you can determine by the return value. Note that the copy (child) is not a "perfect" copy: for example, in the child, all threads are terminated except for the one executing fork. The exact behavior is a bit complex.

  2. It's not specified whether the parent or child process continues execution first. This depends on your OS and might even be totally random on your OS. Since they are two separate processes (which happen to run the same code) the order doesn't matter. The parent process will get a return value >0 (or -1 on error) and thus execute the default: label. The child process will get a return value of 0 and thus execute the case 0: label. This return value of fork is how the parent process knows it's a parent and the child process that it is a child (the child can query its own PID using getpid(2) and the PID of its parent using getppid(2)).

  3. Yes, the parent runs into the default: label and executes _exit, thus terminating. The child will continue to run (note that here setsid() is very important; without it, the child would not continue to run if the shell session of your parent exits). This is the usual pattern for creating a daemon: when you run the program, it spawns actual main program (the daemon) through forking and then exits. For example, in the shell, you'll see the program exits quickly, but when you enter ps you can see that there's a process with the same name (your daemon).

Upvotes: 2

caskey
caskey

Reputation: 12695

Yes, when the parent executes it will continue in the default: case as the switch will have returned the child process id.

The common convention of saying that fork() is a function which is called once and returns two times is a bit obfuscating as it only returns once in each process space. The question is whether a child was created or not which determines which of the two ways a parent returns. The parent never gets a result of '0' from fork(), only either -1 or >0. The child always (if at all) gets zero.

If the child wasn't created, then fork() never returns in its process space.

Upvotes: 2

Related Questions