A fork has already occurred in code:
if (pid == 0) {
printf("I am child PID %d\n", getpid());
exit(EXIT_SUCCESS);
} else {
pid_t child;
int status;
//need wait() function that gets child pid and exit status
printf("Child PID %d terminated with return status %d\n", child, status);
}
As commented in the code, I need an appropriate wait function that will wait for child to end and get the PID and resulting exit status code of the child. Thanks!
You can use wait(), or waitpid() (same page, really).
Or, if you're on BSD, wait3(), or wait4() (but not, AFAIK, wait2()).
Related
int main() {
pid_t pid;
printf("Parent: %d\n", getpid());
pid = fork();
if (pid == -1) {
perror("fork");
goto clean_up;
} else if (pid > 0) {
sleep(3);
} else {
printf("Child Parent: %d\n", getppid());
printf("Child: %d\n", getpid());
printf("Exiting...\n");
}
clean_up:
return 0;
}
I wanted to create zombie process on purpose (of course for experimenting/learning). After the child exits, the parent doesn't wait()s for the child. So, I'm expecting zombie to show up, in ps -ef | grep zombie.o. But for some reason it is not showing up. What could be the possible reasons?
When the parent exits, all its children (alive or zombie) are assigned PID 1 as their new parent. See the _exit(2) man page: " any children of the process are inherited by process 1".
PID 1 is normally the init daemon, and if it's working properly then it should always wait() for its children. So zombie children will be reaped immediately, and children that are still running will be reaped as soon as they exit.
If you want to create a long-lived zombie, the parent needs to remain alive but not calling wait().
I am trying to understand how and does waitpid() using WNOHANG actually clean the resources of the child it's supposed to wait for?
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
printf("Hello from start\n");
int pid;
if((pid = fork()) == 0){
printf("Hello from child: %d\n", getpid());
printf("My parent PID is: %d\n", getppid());
}else if(pid > 0){
printf("Hello from parent: %d\n", getpid());
int status;
waitpid(pid, &status, WNOHANG);
}else{
perror("ERROR");
}
printf("Outside if statement, pid is: %d\n", getpid());
}
The output for child process for parent PID is: 1 meaning parent terminated and child was zombie passed to init process.
From what I understood WNOHANG in man description, it's supposed to return whether child process terminated at the time of testing it and let parent process continue on. I however thought that if parent was about to terminate before its child, it would wait for child to "clean it up". From this it seems that the parent just keeps on going and terminates without cleaning up.
What am I missing, and how to let parent continue its work but not let it terminate without waiting for child to terminate first?
Thanks!
I however thought that if parent was about to terminate before its child, it would wait for child to "clean it up".
That is not the case. The parent won't wait. Children of a process that terminates get reparented to process 1, and they will automatically get reaped when they terminate.
how to let parent continue its work but not let it terminate without waiting for child to terminate first?
work();
int status;
waitpid(pid, &status, 0);
I am a bit confused about why the child process in the following two programs is showing different parents ids.
First program:
int main ( void ) {
int pid, fpid, ppid;
fpid = fork ();
pid = getpid();
ppid = getppid();
printf ("fpid is %d\n", fpid);
sleep(5);
if (fpid > 0){
printf ("\nThis is Parent. My pid %d. My parent's pid %d\n",pid,ppid);
}
else if (fpid ==0){
sleep(1);
printf ("\nThis is Child. My pid %d. My parent's pid %d\n",pid,ppid);
}
else
printf ("fork failed\n");
return (0);
}
Output:
fpid is 53560
fpid is 0
This is Parent. My pid 53559. My parent's pid 44632
MacBook-Pro:~/Desktop/$
This is Child. My pid 53560. My parent's pid 53559
Second program:
int main ( void ) {
int pid, fpid, ppid;
fpid = fork ();
printf ("fpid is is %d\n", fpid);
sleep(5);
if (fpid > 0){
pid = getpid();
ppid = getppid();
printf ("\nThis is Parent. My pid %d. My parent's pid %d\n",pid,ppid);
}
else if (fpid ==0){
sleep(1);
pid = getpid();
ppid = getppid();
printf ("\nThis is Child. My pid %d. My parent's pid %d\n",pid,ppid);
}
else
printf ("fork failed\n");
return (0);
}
Output:
fpid is is 53635
fpid is is 0
This is Parent. My pid 53634. My parent's pid 44632
MacBook-Pro:~/Desktop$
This is Child. My pid 53635. My parent's pid 1
I understand that process 1 is the process that takes over as a parent once the original parent terminates. I guess what I want to know is: isn't the parent process being finished before the child process can process its printf in both cases? Shouldn't the outputs be the same?
Since parent and child processes run concurrently, the order of execution depends on runtime. One of them can finish earlier. When parent finishes before child reaches its getppid(), child process would be adopted by init. Hence the parent id 1.
To see child's actual parent process id:
Let the parent wait for its child termination using wait() or waitpid(), or
Let parent sleep for some perceivable amount like sleep(120) after 'This is parent' printf().
isn't the parent process being finished before the child process can process it's printf in both cases?
Very likely so, but not absolutely certain. You cannot ensure that by sleep()ing for any length of time.
Shouldn't the outputs be the same?
They could be the same, but they are unlikely to be. It's important to note when in each program getppid() is called. The parent process ID reported is the one that applied at the time of the call; it is not necessarily still applicable later, when the value is printed.
First, I fork a child to do something,
and I use waitpid(-1, &child_status, WNOHANG); in the parent to let parent continue instead of waiting for child to finish.
How do I know when the child finished its process?
You can set up a signal handler for SIGCHLD which gets sent automatically when a child process exits.
The signal processor can then set a global flag which can be periodically checked in other parts of the program. If the flag is set, call wait or waitpid to get the child's exit status.
int child_exit_flag = 0;
void child_exit(int sig)
{
child_exit_flag = 1;
}
...
signal(SIGCHLD, child_exit);
...
if (child_exit_flag) {
pid_t pid;
int status;
child_exit_flag = 0;
pid = wait(&status);
printf("child pid %d exited with status %d\n", pid, status);
}
The code:
int main(void)
{
printf("pid: %d\n", getpid());
pid = fork();
if (pid < 0) {
fprintf(stderr, "Fork Failed!");
exit(-1);
} else if (pid == 0) {
execv("sum", argv);
} else {
printf(" pid: %d\n", pid);
wait(NULL);
}
}
The output:
pid: 280
pid: 281
The question:
Why are the two pid's different. I thought they should be the same because the parent is what is executing in the else block and the parent is what is executing before the fork so they should be the same, no?
RETURN VALUE
On success, the PID of the child process is returned in the parent,
and 0 is returned in the child. On failure, -1 is returned in the parent,
no child process is created, and errno is set appropriately.
So, in the parent process, fork() returns the pid of the child process that was created.
I won't repeat nos's answer, as he's entirely correct. But I'd point out that any program can retrieve it's own PID with the getpid system call. So there's no reason for the fork to return you own PID. Instead, you may want to know the PID of the process you just forked off, which may be difficult to obtain if it wasn't returned (to the parent) by fork.