Search code examples
c++clinuxunixfork

Should we use exit or return in child process


Saying that I have used fork to create one child process. Here is an example:

pid_t pid=fork();
if (pid==0) /* child */
{
    // do something
    exit(0); // _exit, exit or return????
}
else /* parrent */
{
    wait(nullptr);
    return 0;
}

I've seen many examples of fork. Some of them used _exit to terminate the child process to avoid flush the I/O buffer, others used exit to terminate the child process. But non of them used return. As my understanding, _exit and exit won't call destructors automatically, so is it better to call return instead of exit in the child process? Or because all examples that I've ever seen are C, instead of C++, so they don't need to worry about destructors?


Solution

  • You can use either _exit or exit, but you shouldn't use return. When you fork a child, you retain the entire call stack as part of forking the child. So if you use return, you end up returning up all the way through your program, potentially continuing on and performing other tasks, which is almost certainly not what you want.

    For example, if you have something like this snippet:

    int get_value()
    {
        pid_t pid;
        if (!(pid = fork())) {
            int x = 0;
            // do something with x.
            exit(x);
        }
        else {
            int status;
            wait(&status);
            return status;
        }
    }
    
    int main()
    {
        int value = get_value();
        switch (get_value()) {
            case 0:
                // call f
                break;
            case 255 << 8:
                // call g
                break;
        }
    }
    

    you'll could end up calling f or g or doing other work with return, which is definitely not desired.

    If you call _exit, functions that are registered with atexit are not called. This is the right thing to do in threaded environments. If you're not working in a threaded environment and you don't have any handlers registered with atexit, then they should be functionally equivalents.

    If you want destructors in your child process to be called, put the child process code in its own function and let its variables be automatically destroyed when they go out of scope. exit will not destroy objects for you, which is good because usually you do not want to destroy objects created in the parent process in your child process.