The purpose of the wait() in parent c - c

I am new to processes in linux and c.
I am using this straightforward example:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, const char * argv[]) {
pid_t child_pid_or_zero = fork(); //fork returns twice
if(child_pid_or_zero < 0)
{
//if fork returns a number smaller than zero, something wrong happened
perror("Something wrong happened\n");
exit(-1);
}
if(child_pid_or_zero > 0)
{
//if fork returns a number greater than zero, this is the parent process
printf("I'm the parent, my pid is: %d\t My child pid is %d\n", getpid(), child_pid_or_zero);
wait(NULL);
}
else
{
//this means that fork now returned 0, the child process is running
printf("I am the child with pid: %d\t My parent pid is: %d\n",child_pid_or_zero, getppid());
}
return 0;
}
If I were to omit the wait() method in the
if(child_pid_or_zero > 0)
What would happen? I tried this myself, and apparently, there was no immediate difference. Do we always need to use a wait(), or does this only apply when the child is supposed to perform heavy calculations etc ?
Thanks in advance.

Wait is for listening to state changes and obtaining information about the child. A state change is child termination, stopping or resuming by a signal. Wait allows the system to release the resources associated with the child. If a wait is not performed, then the terminated child remains in a "zombie" state.
The kernel maintains a minimal set of information about the zombie
process (PID, termination status,
resource usage information) in order to allow the parent to later perform a wait to obtain information about the child. As long
as a zombie is not removed from the system via a
wait, it will consume a slot in the kernel process table, and if this table fills, it will not be possible to create further
processes. If a parent process terminates, then its
"zombie" children (if any) are adopted by init(1), which automatically performs a wait to remove the zombies.

The system call wait(2) is typically used to find if the child process's state has changed (i.e. whether it's still running, exited, etc).
Another purpose is to avoid "zombie" processes. If parent process doesn't wait on the child process and the child process exits before the parent process then it becomes a "zombie" process. So, a wait() call is used to "reap" the process and release the system resources associated with the process.
Imagine if the parent process is a long running one and creates several child processes at regular intervals then all the zombie processes will have entries in the process table which is an unncessary use of system resources.

after the fork, you'll have two independent process.
whit the wait() call, you tell the parent process to wait the child process to terminate.
In this example, nothing changes since the two process are not interacting with each other, so the parent can just exit after creating the child and printing the string, but in the scenario where the parent has to wait the child to do some operations and then maybe return some values to the parent, it becomes useful!

Related

Using fork(), how can I make child process run always first?

Child and parent process execution is parallel and which starts first depends on OS scheduling. But what can be done to start child always before the parent?
This is the pseudo code for my problem,
int start_test()
{
pid_t pid;
pid = fork();
if(pid == 0) {
execv("XXX", XXX);
} else if(pid > 0) {
pid = fork();
if(pid == 0) {
execv("XXX", XXX);
} else {
// Do something
}
}
return 0;
}
int main()
{
start_test();
return 0;
}
I wants to make first execv execute first than parent creates new process again. Every execv should be in sequence.
I don't really know why people keep telling not to rely on this behaviour, it's actually used a lot in tracing programs (strace, ldtrace, ...).
First, fork your process and get the child pid, stop the child, and resume it in the parent:
pid_t pid = fork();
if (pid == -1)
abort();
else if (pid == 0) {
raise(SIGSTOP); // stop the child
} else {
waitpid(pid, NULL, WUNTRACED); // wait until the child is stopped
kill(pid, SIGCONT); // resume the child
}
You can achieve this thing in case of pthread (POSIX thread), but not in case of process.
See, the process scheduling is always in the hands of kernel and that you cannot manipulate explicitly. In a parallel-processing system all processes (whether it is child process, parent process or other zombie process) all are executed in parallel, that you cannot change.
The sleep() method could work, but it is very poor approach to be followed.
1. By making use of signal handling.
When you fork() a new child process, just then you sleep() or pause() the parent process. Child process will be executed where as the parent process will be in waiting position. And then child process sends custom signal which will be handeled by parent process to continue the execution.
(This is also hectic, because you need to handle signal in program).
2. By using the system calls.
By making use of system calls you can handle the process state (ready, suspend, terminate, etc). There are certain shell commands that implicitly uses the system-signal-handling to change the process state/priority. If you know the processID (pid) then you can do:
kill -SIGSTOP [pid]
kill -SIGCONT [pid]
And in case of c-programming you can do:
system("kill -SIGSTOP [pid]"); //pause
and
system("kill -SIGCONT [pid]"); //resume
For more reference you can open this page.
Moreover, if you can you specify the actual problem where you are going to implement this thing, i could suggest you suitably.
Use a binary semaphore with initial value 0. After fork, parent should wait on the semaphore. After child starts, it can signal the semaphore (i.e., make it 1). Then, parent's wait would be over and it will progress.
In linux if you want the child process run first, you need to use kernel.sched_child_runs_first sysctl parameter
There is no guarantee for one process to be scheduled before another. Even if you put the parent to sleep(), it could very well happen that the child executes first, if other processes have preempted the parent right after the fork. The child and parent can very well run truly in parallel on two CPUs.
Actually, there is no value in doing so. If some kind of synchronization is required between the two processes, use an explicit mechanism like pipes/signals, etc.
In short: do not write code to rely on behaviour that is not guaranteed.
Threads provide more mechanisms to synchronize parallel code execution. You might have a look at pthread. Note that threads – different from processes – share resources like memory, etc. which may impose other problems.
Just put wait(0); inside the parent.
So parent will wait until child is done.
if(child){
//do whatever
}
if(parent{
wait(0);
// so whatever
}

Zombie process vs Orphan process

A Zombie is created when a parent process does not use the wait system call after a child dies to read its exit status, and an orphan is child process that is reclaimed by init when the original parent process terminates before the child.
In terms of memory management and the process table how are these processes handled differently, specifically in UNIX?
What is an example or extreme case when the creation of zombies or orphans can be detrimental to the greater application or system?
When a child exits, some process must wait on it to get its exit code. That exit code is stored in the process table until this happens. The act of reading that exit code is called "reaping" the child. Between the time a child exits and is reaped, it is called a zombie. (The whole nomenclature is a bit gruesome when you think about it; I recommend not thinking about it too much.)
Zombies only occupy space in the process table. They take no memory or CPU. However, the process table is a finite resource, and excessive zombies can fill it, meaning that no other processes can launch. Beyond that, they are bothersome clutter, and should be strongly avoided.
If a process exits with children still running (and doesn't kill its children; the metaphor continues to be bizarre), those children are orphans. Orphaned children are immediately "adopted" by init (actually, I think most people call this "reparenting," but "adoption" seems to carry the metaphor better). An orphan is just a process. It will use whatever resources it uses. It is reasonable to say that it is not an "orphan" at all since it has a parent, but I've heard them called that often.
init automatically reaps its children (adopted or otherwise). So if you exit without cleaning up your children, then they will not become zombies (at least not for more than a moment).
But long-lived zombies exist. What are they? They're the former children of an existing process that hasn't reaped them. The process may be hung. Or it may be poorly written and forgets to reap its children. Or maybe it's overloaded and hasn't gotten around to it. Or whatever. But for some reason, the parent process continues to exist (so they aren't orphans), and they haven't been waited on, so they live on as zombies in the process table.
So if you see zombies for longer than a moment, then it means that there is something wrong with the parent process, and something should be done to improve that program.
When a process terminates, its resources are deallocated by the operating
system. However, its entry in the process table must remain there until the
parent calls wait(), because the process table contains the process’s exit status.
A process that has terminated, but whose parent has not yet called wait(), is
known as a zombie process. All processes transition to this state when they
terminate, but generally they exist as zombies only briefly. Once the parent
calls wait(), the process identifier of the zombie process and its entry in the
process table are released.
Now consider what would happen if a parent did not invoke wait() and
instead terminated, thereby leaving its child processes as orphans. Linux and
UNIX address this scenario by assigning the init process as the new parent to orphan processes. The init process periodically
invokes wait(), thereby allowing the exit status of any orphaned process to be
collected and releasing the orphan’s process identifier and process-table entry.
Source: Operating System Concepts by Abraham, Peter, Greg
An orphan process is a computer process whose parent process has finished or terminated, though it (child process) remains running itself.
A zombie process or defunct process is a process that has completed execution but still has an entry in the process table as its parent process didn't invoke an wait() system call.
Orphan -
Parent exit , Init process becomes the parent of child process.
Whenever child is terminated, process table gets deleted by os.
Zombie -
When the child terminates it gives exit status to parent.
Meanwhile time suppose your parent is in sleep state and unable to receive any status from child.
Though the child exit but the process occupies space in process table
check out this command in linux ubuntu >>ps -eo pid,ppid,status,cmd
If you found something like defunc at the end i.e your process is zombie and occupying space.
Zombie Process:
A process that has finished the execution but still has an entry in the process table to report to its parent process is known as a zombie process. A child process always first becomes a zombie before being removed from the process table. The parent process reads the exit status of the child process which reaps off the child process entry from the process table.
Orphan Process:
A process whose parent process no more exists i.e. either finished or terminated without waiting for its child process to terminate is called an orphan process.
There are no orphans but the process using PID 1.
From the running process' point of view it makes no difference whether it was started directly and therefore has PID 1 as parent or got inherited by PID 1 because its original parent (being different from PID 1) ended.
It is handled like any other process.
Each process goes through some sort of zombie state, when ending, namely the phase between announcing its end by issuing SIGCHLD and having its processing (delivery or ignorance) acknowledged.
When the zombie state had been entered the process is just an entry in the system's process list.
The only significant resource a zombie is exclusively using is a valid PID.
I would like to add 2 code snippets featuring an orphan and a zombie process. But first, I will post the definition of these processes as stated in the book "Operating System Concepts" by Silberschatz, Galvin and Gagn:
If no parent waiting (did not invoke wait()) process is a zombie
If parent terminated without invoking wait , process is an orphan
Orphan
// A C program to demonstrate Orphan Process.
// Parent process finishes execution while the
// child process is running. The child process
// becomes orphan.
#include <stdio.h> //printf
#include <stdlib.h> //exit
#include <sys/types.h> //fork
#include <unistd.h> //fork and sleep
int main()
{
// Fork returns process id
// in parent process
pid_t child_pid = fork();
// Parent process didn't use wait and finished before child
// so the child becomes an orphan process
// Parent process
if (child_pid > 0) {
printf("I finished my execution before my child");
}
else // Child process
if (child_pid == 0) {
sleep(1); //sleep for 1 second
printf("This printf will not be executed");
}
else{
//error occurred
}
return 0;
}
Output
I finished my execution before my child
Zombie
// A C program to demonstrate Zombie Process.
// Child becomes Zombie as parent is not waiting
// when child process exits.
#include <stdio.h> //printf
#include <stdlib.h> //exit
#include <sys/types.h> //fork
#include <unistd.h> //fork and sleep
int main()
{
// Fork returns process id
// in parent process
pid_t child_pid = fork();
// Parent process didn't use wait
// so the child becomes a zombie process
// Parent process
if (child_pid > 0){
sleep(1); //sleep for 1 second
printf("\nI don't wait for my child");
}
else // Child process
if(child_pid == 0){
printf("My parent doesn't wait me");
exit(0);
}
else{
//error occurred
}
return 0;
}
Output
My parent doesn't wait me
I don't wait for my child
Edit: Source and inspiration taken from here
A process which has finished the execution but still has the entry in the process table to report to its parent process is known as a zombie process.
A process whose parent process no more exists i.e. either finished or terminated without waiting for its child process to terminate is called an orphan process
Here is one summary
Zombie Process
Orphan Process
A Zombie is a process that has completed its task but still, shows an entry in a process table.
A child process that remains running even after its parent process is terminated or completed without waiting for the child process execution is called an orphan.
Zombie process states always indicated by Z
The orphan process was created unknowingly due to a system crash.
The zombie process is treated as dead they are not used for system processing
An orphan process is a computer process even after its parent terminates init it becomes a parent and continues the remaining task.
wait() system call is used to deal with zombie processes
Kernel allocates a new process as parent process to orphan process. Mostly the new parent is the init process (pid=1).
To remove the zombie process executes the kill command.
Terminate the Orphan process using the SIGHUP signal.
Source:
Zombie vs. Orphan Processes
Difference between zombie orphan and daemon processes
Zombie and Orphan Process in OS

Is it a zombie?

I have some doubt regarding the following code.
#include <stdio.h>
#include <sys/types.h>
int main(void)
{
int pid=fork();
if(pid==0) sleep(5);
printf("Hello World %d %d\n",getpid(),pid);
if(pid>0) while(1){sleep(1);}
if(pid==0) printf("In child process!\n");
return 0;
}
Will the child process ever terminate? Will it remain in zombie state?
In your example, the child process dies but the parent doesn't know about it's exit status. As such, the child (now zombie) is left in the process table.
Moreover, the parent continues to wait for the child and keeps running.
Yes it is zombie ... your Child process dies and your parent does not know the exit status of child process. and parent process is running even after child dies.
ZOMBIE process: when child process dies parent process still running. in this case parent process does not know the exit status of child.
To avoid this parent process uses wait or waitpid to know the child status.
Adding on to other responses.. If the opposite were to happen i.e. Parent dies before the child process completes, then the child would become an orphan and would later be "adopted" by a special system process called init.

C forks, kill the parent after returning its PID

I'm new to C and I've been investigating about forks the last two weeks, I have to solve this problem for my Operative Systems class:
"You must create a "heavy weight" process using a fork, then the first process must wait for the second (the new one) to return its parent id, then it must kill its parent and finish"
I think the instructions are quite confusing, this is my code so far ( As I said, I'm new to C so I've been just investigating)
My problem seems to be that the parent is not even waiting for the child process to return its id, because after that, the child is killing the parent, so I think I'm creating the child process, and when it runs it kills the parent at the end, not letting the parent to wait for the child execution. (that's the part I think is confusing about the instructions)
I want to know more about forks and processes, like the logic behind them so I can feel more sure when coding.
Thanks!
#include <sys/types.h>
#include <wait.h>
#include <unistd.h>
#include <stdio.h>
int main() {
pid_t idProceso;
int childState;
idProceso = fork();
if (idProceso == 0){
printf ("child id : %d. parent id %d\n",
getpid(), getppid());
int parent = getppid();
kill(parent, SIGKILL);
printf ("dead parent"); // not sure about it ??
_exit();
}
if(idProceso > 0){
sleep (1);
printf ("parent id : %d. child id %d\n",
getpid(), idProceso);
wait (&childState);
}
return 0;
}
Based on the assignment description you gave, I think the instructor or professor who assigned it does not have a good handle on either the English language or the concept of processes on a Unix machine.
The solution you presented is reasonable, but I would I remove the call to sleep. Childstate is never set correct, and you don't need it all. Additionally, don't send SIGKILL to the parent. SIGKILL is the last way to attempt to terminate a process. I suggest sending SIGTERM to the parent process. The parent process can install a signal handler with sigaction if you are using a Linux machine. In the signal handler, you can print a nice message like "Received terminate signal from child" and call exit. If you do this your professor will probably be suitably impressed with your skills to give you a passing grade.
Failing that, I would ask for a better problem. It was not uncommon for me to have to submit grammatical and punctuation corrections to professors for approval before actually solving the problem.
My problem seems to be that the parent is not even waiting for the
child process to return its id
Nowhere in your program is the child returning its id to the parent. The only comunication that is happening is the child sending a SIGKILL signal to the parent.
so I think I'm creating the child process, and when it runs it kills
the parent at the end, not letting the parent to wait for the child
execution.
Yes , you are right , the child will kill the parent process , by sending a SIGKILL signal , using the kill() function , but the parent actually waits to get killed by the child.
wait (&childState);
This here makes the parent wait(hang there) for the child to terminate , after termination , the parent will move on , but in your program , while the parent waits for the child to get terminated , the child itself will terminate the parent during the wait.
I want to know more about forks and processes, like the logic behind
them so I can feel more sure when coding.
This is something worth looking at.
$ ./foo.bin
parent id : 6629. child id 6630
child id : 6630. parent id 6629
dead parentKilled
I just removed the sleep(1) and the output seems to be reasonable.

Why fork() twice [duplicate]

This question already has answers here:
What is the reason for performing a double fork when creating a daemon?
(9 answers)
Closed 8 years ago.
Nagios lets me configure child_processes_fork_twice=<0/1>.
The documentation says
This option determines whether or not Nagios will fork() child processes twice when it executes host and service checks. By default, Nagios fork()s twice. However, if the use_large_installation_tweaks option is enabled, it will only fork() once.
As far as I know fork() will spawn a new child process. Why would I want to do that twice?
All right, so now first of all: what is a zombie process? It's a process that is dead, but its parent was busy doing some other work, hence it could not collect the child's exit status. In some cases, the child runs for a very long time, the parent cannot wait for that long, and will continue with it's work (note that the parent doesn't die, but continues its remaining tasks but doesn't care about the child). In this way, a zombie process is created. Now let's get down to business. How does forking twice help here? The important thing to note is that the grandchild does the work which the parent process wants its child to do. Now the first time fork is called, the first child simply forks again and exits. This way, the parent doesn't have to wait for a long time to collect the child's exit status (since the child's only job is to create another child and exit). So, the first child doesn't become a zombie. As for the grandchild, its parent has already died. Hence the grandchild will be adopted by the init process, which always collects the exit status of all its child processes. So, now the parent doesn't have to wait for very long, and no zombie process will be created. There are other ways to avoid a zombie process; this is just a common technique. Hope this helps!
In Linux, a daemon is typically created by forking twice with the intermediate process exiting after forking the grandchild. This has the effect of orphaning the grandchild process. As a result, it becomes the responsibility of the OS to clean up after it if it terminates. The reason has to do with what are known as zombie processes which continue to live and consume resources after exiting because their parent, who'd normally be responsible for the cleaning up, has also died.
Also from the documentation,
Normally Nagios will fork() twice when it executes host and service checks. This is done to (1) ensure a high level of resistance against plugins that go awry and segfault and (2) make the OS deal with cleaning up the grandchild process once it exits.
Unix Programming Faq §1.6.2:
1.6.2 How do I prevent them from occuring?
You need to ensure that your parent process calls wait() (or
waitpid(), wait3(), etc.) for every child process that terminates;
or, on some systems, you can instruct the system that you are
uninterested in child exit states.
Another approach is to fork() twice, and have the immediate child
process exit straight away. This causes the grandchild process to be
orphaned, so the init process is responsible for cleaning it up. For
code to do this, see the function fork2() in the examples section.
To ignore child exit states, you need to do the following (check your
system's manpages to see if this works):
struct sigaction sa;
sa.sa_handler = SIG_IGN;
#ifdef SA_NOCLDWAIT
sa.sa_flags = SA_NOCLDWAIT;
#else
sa.sa_flags = 0;
#endif
sigemptyset(&sa.sa_mask);
sigaction(SIGCHLD, &sa, NULL);
If this is successful, then the wait() functions are prevented from
working; if any of them are called, they will wait until all child
processes have terminated, then return failure with errno == ECHILD.
The other technique is to catch the SIGCHLD signal, and have the
signal handler call waitpid() or wait3(). See the examples section
for a complete program.
This code demonstrates how to use the double fork method to allow the grandchild process to become adopted by init, without risk of zombie processes.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
int main()
{
pid_t p1 = fork();
if (p1 != 0)
{
printf("p1 process id is %d", getpid());
wait();
system("ps");
}
else
{
pid_t p2 = fork();
int pid = getpid();
if (p2 != 0)
{
printf("p2 process id is %d", pid);
}
else
{
printf("p3 process id is %d", pid);
}
exit(0);
}
}
The parent will fork the new child process, and then wait for it to finish. The child will fork a grandchild process, and then exit(0).
In this case, the grandchild doesn't do anything except exit(0), but could be made to do whatever you'd like the daemon process to do. The grandchild may live long and will be reclaimed by the init process, when it is complete.

Resources