From the manual page I know that:
exit()
flushes output buffers while _exit
,_Exit
,exit_group
don’t.
In the code below, the content of test.log
will be hellonhellon
only if exit()
was called in child process, which is the same as I tested.
But when there’s no statements in child process, it will behave like it’s calling exit()
, the content of test.log
will be hellonhellon
too.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
int pid;
FILE *fp = fopen("test.log", "w");
fprintf(fp, "hellon");
pid = fork();
if (pid == 0)
{
// do something
;
}
else
{
wait(NULL);
exit(1);
}
}
Through ltrace
and strace
I can see both parent and child called exit_group
.
Since I called exit
in parent, so it can be judged by using ltrace
that exit
will call exit_group
.
But in the opposite I can’t judge whether child process called exit
.
Does gcc called exit
in child process implicitly? It may be harmful to call exit
in child process as many people said. If not, then why the buffer was flushed?
Testing gcc and glibc version:
- gcc version 6.3.0 20170516 (Debian 6.3.0-18+deb9u1)
- GNU C Library (Debian GLIBC 2.24-11+deb9u4) stable release version
2.24
2
Answers
Promoting PSkocik’s comment to an answer:
Returning from
main
is always equivalent to callingexit()
. Either way is supposed to represent "normal" termination of a process, where you want for all the data you buffered to actually get written out, allatexit()
cleanup functions called, and so on.Indeed, the C library’s startup code is often written simply as
exit(main(argc, argv));
If you want the "harsher" effect of
_exit()
or_Exit()
then you have to call them explicitly. And a forked child process is a common instance where this is what you do want.You have a statement in child process (implicit):
When child process returns from
main()
, the C runtime makes a call toexit(0);
(or better, something equivalent toexit(main(arc, argv, envp));
, indeed) that implies the flushing of buffers you are trying to avoid.If you want to eliminate one of the
hellon
s, justfflush(fp);
before calling tofork()
system call, as the call will duplicatefp
in both processes, each with a partially full buffer the same way, and this is the reason you get the buffer contents duplicated. Or better flush all output buffers withfflush(NULL);
.