ned1986zha
ned1986zha

Reputation: 815

What is the difference between using _exit() & exit() in a conventional Linux fork-exec?

I've been trying to figure out how the fork-exec mechanism is used inside Linux. Everything was going on according to the plan until some web pages started to confuse me.

It is said that a child process should strictly use _exit() instead of a simple exit() or a normal return from main().

As I know, Linux shell fork-execs every one of the external commands; assuming what I said above is true, the conclusion is that none of these external commands nor any other execution happening inside the Linux shell can do normal return!

Wikipedia & some other webpages claim we've got to use _exit() just to prevent a child process causing deletion of parent's temporary files while a probable double flushing of stdio buffers may happen. though I understand the former, I have no clues how a double flushing of buffers could be harmful to a Linux system.

I've spent my whole day on this... Thanks for any clarification.

Upvotes: 77

Views: 57448

Answers (5)

Hindavi Lande
Hindavi Lande

Reputation: 1

In Unix systems, exit() and _exit() are both used for terminating a process, but they differ in their behavior, particularly in how they handle process termination and cleanup:

  1. exit():

    • exit() is a standard C library function used to terminate a process normally. When you call exit(), it performs the following actions:
      • Cleans up resources held by the process, including closing open file descriptors.
      • Flushes buffered I/O streams (e.g., stdout, stderr).
      • Calls registered cleanup functions (using atexit()).
      • Returns control to the operating system.
    • exit() is a higher-level function and performs various cleanup tasks before terminating the process.
  2. _exit():

    • _exit() is a system call used to terminate a process immediately without performing any cleanup tasks. When you call _exit(), it:
      • Immediately terminates the process without flushing buffers, closing files, or running cleanup code.
      • Doesn't execute registered atexit() functions or call any functions registered with on_exit().
      • This function is more low-level and does not perform any kind of cleanup or finalization.

Upvotes: 0

In the child branch of a fork(), it is normally incorrect to use exit(), because that can lead to stdio buffers being flushed twice, and temporary files being unexpectedly removed.

Excerpted from: http://www.unixguide.net/unix/programming/1.1.3.shtml

Upvotes: 0

Sandeep_black
Sandeep_black

Reputation: 1441

exit() is on the top of _exit(), using conventional C library.

There are the differences:

  1. _exit() won't flushes the stdio buffer while exit() flushes the stdio buffer prior to exit.

  2. _exit() can not perform clean-up process while exit() can be registered with some function ( i.e on_exit or at_exit) to perform some clean-up process if anything is required before existing the program.

exit(status) simply passes the exit status to _exit(status). It is recommended that whenever to perform fork(), one of them between child and parent, one use _exit() and another use exit().

Upvotes: 9

Nandan Bharadwaj
Nandan Bharadwaj

Reputation: 560

exit() flushes io buffers and does some other things like run functions registered by atexit(). exit() invokes _end( )

_exit() just ends the process without doing that. You call _exit() from the parent process when creating a daemon for example.

Ever notice that main() is a function? Ever wonder what called it in the first place? When a c program runs the shell you are running in provides the executable path to 'exec' system call and the control is passed to kernel which in turn calls the startup function of every executable _start(), calls your main(), when main() returns it then calls _end() Some implementations of C use slightly different names for _end() & _start() ...

exit() and _exit() invoke _end()

Normally - for every main() there should be one & only one exit() call. (or return at the end of main() )

Upvotes: 19

Fred Foo
Fred Foo

Reputation: 363607

You should use _exit (or its synonym _Exit) to abort the child program when the exec fails, because in this situation, the child process may interfere with the parent process' external data (files) by calling its atexit handlers, calling its signal handlers, and/or flushing buffers.

For the same reason, you should also use _exit in any child process that does not do an exec, but those are rare.

In all other cases, just use exit. As you partially noted yourself, every process in Unix/Linux (except one, init) is the child of another process, so using _exit in every child process would mean that exit is useless outside of init.

switch (fork()) {
  case 0:
    // we're the child
    execlp("some", "program", NULL);
    _exit(1);  // <-- HERE
  case -1:
    // error, no fork done ...
  default:
    // we're the parent ...
}

Upvotes: 69

Related Questions