I am getting segmentation fault in the following program.
Why? And how to resolve it?
#include <stdio.h>
main()
{
int pid;
printf("I'm the original process with PID %d and PPID %d.\n", getpid(),getppid());
pid=vfork();
if (pid!=0)
{
printf("I'm the parent process with PID %d and PPID %d.\n",getpid(),getppid());
printf("My child's PID is %d.\n", pid);
}
else
{
printf("I'm the child process with PID %d and PPID %d.\n",getpid(),getppid());
}
}
Output:
I'm the original process with PID 18563 and PPID 18500.
I'm the child process with PID 18564 and PPID 18563.
I'm the parent process with PID 18563 and PPID 18500.
My child's PID is 18564.
Segmentation fault
From vfork man page
(From POSIX.1) The vfork() function has the same effect as fork(2),
except that the behavior is undefined if the process created by
vfork() either modifies any data other than a variable of type pid_t
used to store the return value from vfork(), or returns from the
function in which vfork() was called, or calls any other function
before successfully calling _exit(2) or one of the exec(3) family of
functions.
You are returning before a successful call to _exit, so this behavior is undefined. Try fixing that and see if the problem persists.
A quote from the man page of vfork:
vfork() differs from fork(2) in that the calling thread is suspended until the child terminates (either normally, by calling _exit(2), or abnormally, after delivery of a fatal signal), or it makes a call to execve(2). Until that point, the child shares all memory with its parent, including the stack. The child MUST NOT RETURN FROM THE CURRENT FUNCTION or call exit(3), but may call _exit(2).
Your child process has returned from the function it was created in, so you probably corrupted the stack shared by both threads.
Related
In one of the special cases shown below, getpid() for the grandchild created with vfork() returns the PID of the parent process.
#include <stdio.h>
#include <stdlib.h>
int main() {
if(vfork()) { /* parent */
printf("parent pid = %d\n", getpid());
exit(0);
} else {
if(vfork()) { /* child */
printf("child pid = %d\n", getpid());
exit(0);
} else { /* grandchild */
printf("grandchild pid = %d\n", getpid());
exit(0);
}
}
}
Compiled as gcc main.c, this works as expected:
grandchild pid = 12241
child pid = 12240
parent pid = 12239
Compiled as gcc main.c -lpthread, the grandchild PID is incorrect:
grandchild pid = 12431
child pid = 12432
parent pid = 12431
Any clues why? Is this one of the undefined behavior cases?
With ps and strace, I can see the correct PID. BTW, the same example code works fine with fork(), i.e. correct getpid() with or without -lpthread.
getpid is not one of the two operations you're permitted to perform after vfork in the child; the only two are execve and _exit. It happens that glibc caches the process's pid in userspace, and does not update this cache on vfork (since it would modify the parent's cached value, and since it's not needed since valid code can't observe the result); that's the mechanism of the behavior you're seeing. The caching behavior differs slightly with -lpthread linked. But the underlying reason is that your code is invalid.
Pretty much, don't use vfork. There's basically nothing you can do with it.
From the manual page for vfork():
The vfork() function has the same effect as fork(2), except that the behavior is undefined if the
process created by vfork() either modifies any data other than a variable of type pid_t used to store the return value
from vfork(), or returns from the function in which vfork() was called, or calls any other function before successfully
calling _exit(2) or one of the exec(3) family of functions.
It's not very nicely worded, but what this is saying is that the only things that a child process can do after vfork() are:
Check the return value.
Call one of the exec*() family of functions.
Call _exit().
This is because:
vfork() is a special case of clone(2). It is used to create new processes without copying the page tables of the parent process. It may be useful in performance-sensitive applications where a child is created which then immediately
issues an execve(2).
In other words, the intended use of vfork() is only to create children that will execute other programs through exec*(), making this faster than a normal fork() because the page table of the parent is not duplicated in the child (since it's going to be replaced by exec*() anyway). Even then though, vfork() only has a real advantage if this kind of operation needs to be performed multiple times. Since parent memory is not copied, accessing it in any way is undefined behavior.
here is the requirements for vfork()
#include <sys/types.h>
#include <unistd.h>
pid_t vfork(void);
Notice the OPs posted code fails to include the needed header files.
How to write a programm to show whether it's a child or parent process after the fork() is used?
I need to find other way then checking the return value of fork() or getpid() function.
I know e.g. that process resource utilizations (getrusage(2)) and CPU time counters (times(2)) are reset to zero in the child. How i can use for example that knowledge (or other child-parents differences) to determine my problem?
Thank you for your help!
Setup a signal handler for SIGCHLD in one of the processes and end the other one. If the SIGCHLD handler gets called you know the child died. If not the parent died.
Another (less distructive) way it to call wait(). If it returns ECHLD no child is around, thus the calling process is the child. If it blocks, at least one child is around, thus the calling process is the parent.
Or call waitpid() with PID of the other process. The same logic on the result as for wait() applies.
You could exploit the fact that the parent will be a process group leader (and thus its pid will be the same as its process group id) while the child will be a member of that process group and thus its pid will be different from the process group id:
#include <stdio.h>
#include <unistd.h>
main(int argc, char **argv) {
char *self = NULL;
fork(); /* looking at return value would be cheating */
int pid = getpid();
int pgid = getpgid(0);
if (pid == pgid)
self = "Parent";
else
self = "Child";
printf("%s pid = %d pgid = %d\n", self, pid, pgid);
}
Running yields:
$ ./pgid
Parent pid = 29400 pgid = 29400
Child pid = 29401 pgid = 29400
This does of course still use getpid() but not in the same way you describe above.
On Linux, you might also use proc(5). The process of pid 1234 is described by the directory /proc/1234/ and you could read sequentially and parse the /proc/1234/status pseudo-file to get all that information.
To understand a bit more, read the proc(5) man page, then type
cat /proc/self/status
cat /proc/$$/status
cat /proc/self/maps
cat /proc/$$/maps
in a terminal, and try to understand the output. You might parse it programmatically (e.g. with FILE*f = fopen("/proc/1234/status","r"); then do some fgets or fscanf on f; then fclose(f);)
I have a small program written in C on linux. It's purpose is to examine the behaviour of the fork() call and the resulting child processes
Upon first inspection everything seems simple enough. However
Sometimes output is written in a funny order
Sometimes the child PPID is '1' not whatever the parent PID is.
I can't find any pattern or correlation between when it works as expected and when it does not.
I think that point 2. is probably caused by the parent process dying before the child process has executed fully. If so, is there a way to stop this from happening.
However I have no idea what is causing point 1.
Code below:
#include <stdio.h>
#include <unistd.h>
int main()
{
int x = fork();
if (x == 0)
{
printf("Child:");
printf ("\nChild PID : %d", getpid());
printf ("\nChild PPID: %d", getppid());
printf("\nHello Child World\n");
}
if (x != 0)
{
printf("Parent :");
printf ("\nParent PID : %d", getpid());
printf ("\nParent PPID: %d", getppid());
printf("\nHello Parent World\n");
}
return 0;
}
this behaviour is seen because of scheduling policy of operating system. if you are aware of process management concepts of os, then if your parent code is running and fork() is encountered, child is created, but if within that time, parent's time slice has not been completed, then parent continues running and if within its time slice, parent executes and terminates, then child becomes orphan precess and after parent process' time slice completes, child's execution starts, thats why getppid() function returns 1, because child is an orphan process and it it now adopted by init process which starts first when operating system boots and is having process id 1.
Explanation of Behaviour 1:
The order of output cannot be controlled by the program normally. That's the point of parallel process. The OS decides which process to execute at any point of time and both processes are executed simultaneously (to the human eye).
Thus the output would generally be inter-tweened.
Explanation of Behaviour 2:
You guessed that right.
The parent process has finished before the forked one.
If you want the parent pid, you can use waitpid(x, &status, 0) in the parent process if you need the parent to stay alive till child execution. This link may help you.
#include <stdio.h>
int main(void)
{
fork();
fork();
printf("ppid %d pid %d\n", getppid(), getpid());
return 0;
}
The above code sometimes prints
$ ./a.out
ppid 3389 pid 3883
ppid 3883 pid 3885
ppid 1 pid 3884
ppid 3884 pid 3886
Why is process 3884's ppid 1? Doesn't it supposed to be 3883?
I'd guess the parent process had already completed running and exited by the time the third child checked for the parent's PID. That would have caused the child to be re-parented under init, which has process ID 1.
Taken from:
http://publib.boulder.ibm.com/infocenter/iseries/v5r4/index.jsp?topic=%2Fapis%2Fgetppid.htm
"The value returned by getppid() is the process ID of the parent process for the calling process. A process ID value of 1 indicates that there is no parent process associated with the calling process."
That printf instruction was executed within the parent process, so it returned 1 because it does not have a parent process. It's perfectly normal that this was the 3rd line to be printed, since the fork run its process concurrently and no particular order is guarantied.
To build upon Jamey's answer, when a process finishes before the child's execution and exits, the child becomes an orphan i.e. orphan process so the kernel maps that orphan to the init process.
Using wait() makes sure that the parent waits until the child has finished execution.
I have a program with undefined behavior ( vfork() is used inappropriately ):
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
int main ( int argc, char *argv[] )
{
pid_t pid;
printf("___________befor fork______________.\n");
if((pid=vfork()) < 0)
perror("fork");
else if(pid > 0)
printf("parent\n");
else
printf("child\n");
printf("pid: %d, ppid: %d\n", getpid(), getppid());
//exit(0);
return 0;
}
If I use exit(0) function instead return - output is:
___________befor fork______________.
child
pid: 4370, ppid: 4369
parent
pid: 4369, ppid: 2924
If I use return 0 - I get infinite output like this:
___________befor fork______________.
child
pid: 4455, ppid: 4454
parent
pid: 4454, ppid: 2924
___________befor fork______________.
child
pid: 4456, ppid: 4454
parent
pid: 4454, ppid: 2924
___________befor fork______________.
child
pid: 4457, ppid: 4454
parent
pid: 4454, ppid: 2924
and so on ...
I know that you can not use return in the child after the vfork() function.
But I don't understand why the parent does not end after return call?
Thanks.
It is not valid to return from the function in the child, because with vfork() both the parent and child share the same stack and returning in the child will mess up the stack frame for the parent. Usually the call to main() (in the start function) is followed by a call to exit() or similar, so that call to exit() in the child will overwrite the same stack space that the call to main() was using (and is still using in the parent). So when the child does exit, the parent will return from vfork() but the return address on the stack will likely be clobbered so it could return to any address or do anything at all.
Also, in the child, if you do not exec you should call _exit() rather than exit(). exit() will flush the stdio output buffers but those same buffers are being managed by the parent, whereas _exit() will just end the process.
By returning in your child process you are causing undefined behavior, so anything can really happen.
It looks like you parent process works fine, but the child process, instead of exiting, restarts main function.
you can see the definition of vfork in the kernel.org : http://www.kernel.org/doc/man-pages/online/pages/man2/vfork.2.html . it is a good explanation.
The current POSIX standard does not support vfork() at all.
In the old (1997-ish) POSIX standard, the page for vfork() said:
The vfork() function has the same effect as fork(), except that the behaviour is undefined if the process created by vfork() either modifies any data other than a variable of type pid_t used to store the return value from vfork(), or returns from the function in which vfork() was called, or calls any other function before successfully calling _exit() or one of the exec family of functions.
Your code is not calling either an exec family function or _exit(), so you invoke undefined behaviour, and anything that happens is legitimate.
You've just demonstrated why it is not usually sensible to use vfork(). IMNSHO, it is in the same camp as gets(); I know it exists but I would never use it voluntarily, and I'd be perfectly happy for the implementations to be:
pid_t vfork(void) { abort(); }
char *gets(char *buffer) { abort(); }