Anyone can explain the following code:
#include<stdio.h>
#include<stdlib.h>
main()
{
int a=1;
int pid;
if((pid = vfork()) == 0)
{
printf("This is child . %d\n", getpid() );
a=2;
}
else
{
printf("%d\t%d\n",getpid(),a);
sleep(1);
}
}
In the above code, child processes are created repeatedly. Can anyone please help me understand the logic?
Read the manual page for
vfork
. Especially the part where it tells you what you are allowed to do in the child. You are not allowed to callgetpid
in the child. You are not allowed to callprintf
in the child. You are not allowed to set the variablea
. You are not allowed to return from the function that calledvfork
in the child. You did all those things therefore the code does something unexpected. Unfortunately for you the unexpected thing isn't crashing.You may only call
_exit
or one of theexec*
functions in avfork
:ed child. Nothing else.The
vfork
system call is a optimization hack from the days whenfork
was very expensive. So what it does it to suspend the parent process and use the parents address space in the child (this may or may not be true depending on operating system) until the child callsexec*
or_exit
. Any memory write that the child does will overwrite memory in the parent process. Calling functions will overwrite memory in ways that the parent process doesn't expect. Returning from the function that calledvfork
will definitely overwrite state that the parent expects to be intact (like the return addresses and saved stack pointers). Callingprintf
will overwrite stdio buffers that the parent doesn't expect to be overwritten, etc.It could probably be reasoned why in your case the parent calls itself again after the child exits, after all computers are quite deterministic. If you analyze the crt code that calls main, the various atexit handlers in libc and other cleanup you could probably figure out exactly what happens to write what at the right place on the stack that makes the parent confused and return to the wrong place after the syscall returns. Disassemble the code and go for it. Or you could just search this site for the dozens of other questions about
vfork
and notice that they all follow the same theme: "Why does vfork do something unexpected when I do something the documentation tells me not to do?". It does it because it's undefined behavior and the way undefined behavior behaves is undefined. In your case overwriting memory that the parent didn't expect to have overwritten happened to make the parent call itself again. In other cases I've seen it made printf print twice. In other cases nothing bad happened. In other cases the program crashed.