Error with child process & wait `C` - c

In the below code, if there is a problem creating a child process or something happens to the child process what happens to wait(&status)?
pid_t pid;
int status;
if(pid=fork()){
printf("Parent Process\n");
wait(&status);
} else... child process here

If there is a problem creating a child process, fork will return -1, so this code will never wait.
If there's something happend to the child process, wait will return, and you can observe status.

If the child cannot be created, fork() will return with -1, you should look at errno after that. No error process is created here. Your code does not check this case.
If the child is created and dies, wait() will return the PID of the terminated process, the reason for the child's death is given in status. See the man page for wait on how to extract meaning from status.

Related

How do you kill zombie process using wait()

I have this code that requires a parent to fork 3 children.
How do you know (and) where to put the "wait()" statement to kill
zombie processes?
What is the command to view zombie processes if you have Linux
virtual box?
main(){
pid_t child;
printf("-----------------------------------\n");
about("Parent");
printf("Now .. Forking !!\n");
child = fork();
int i=0;
for (i=0; i<3; i++){
if (child < 0) {
perror ("Unable to fork");
break;
}
else if (child == 0){
printf ("creating child #%d\n", (i+1));
about ("Child");
break;
}
else{
child = fork();
}
}
}
void about(char * msg){
pid_t me;
pid_t oldone;
me = getpid();
oldone = getppid();
printf("***[%s] PID = %d PPID = %d.\n", msg, me, oldone);
}
How do you know (and) where to put the "wait()" statement to kill
zombie processes?
If your parent spawns only a small, fixed number of children; does not care when or whether they stop, resume, or finish; and itself exits quickly, then you do not need to use wait() or waitpid() to clean up the child processes. The init process (pid 1) takes responsibility for orphaned child processes, and will clean them up when they finish.
Under any other circumstances, however, you must wait() for child processes. Doing so frees up resources, ensures that the child has finished, and allows you to obtain the child's exit status. Via waitpid() you can also be notified when a child is stopped or resumed by a signal, if you so wish.
As for where to perform the wait,
You must ensure that only the parent wait()s.
You should wait at or before the earliest point where you need the child to have finished (but not before forking), OR
if you don't care when or whether the child finishes, but you need to clean up resources, then you can periodically call waitpid(-1, NULL, WNOHANG) to collect a zombie child if there is one, without blocking if there isn't any.
In particular, you must not wait() (unconditionally) immediately after fork()ing because parent and child run the same code. You must use the return value of fork() to determine whether you are in the child (return value == 0), or in the parent (any other return value). Furthermore, the parent must wait() only if forking was successful, in which case fork() returns the child's pid, which is always greater than zero. A return value less than zero indicates failure to fork.
Your program doesn't really need to wait() because it spawns exactly four (not three) children, then exits. However, if you wanted the parent to have at most one live child at any time, then you could write it like this:
int main() {
pid_t child;
int i;
printf("-----------------------------------\n");
about("Parent");
for (i = 0; i < 3; i++) {
printf("Now .. Forking !!\n");
child = fork();
if (child < 0) {
perror ("Unable to fork");
break;
} else if (child == 0) {
printf ("In child #%d\n", (i+1));
about ("Child");
break;
} else {
/* in parent */
if (waitpid(child, NULL, 0) < 0) {
perror("Failed to collect child process");
break;
}
}
}
return 0;
}
If the parent exits before one or more of its children, which can happen if it does not wait, then the child will thereafter see its parent process being pid 1.
Others have already answered how to get a zombie process list via th ps command. You may also be able to see zombies via top. With your original code you are unlikely to catch a glimpse of zombies, however, because the parent process exits very quickly, and init will then clean up the zombies it leaves behind.
How do you know (and) where to put the "wait()" statement to kill
zombie processes?
You can use wait() anywhere in the parent process, and when the child process terminates it'll be removed from the system. Where to put it is up to you, in your specific case you probably want to put it immediately after the child = fork(); line so that the parent process won't resume its execution until its child has exited.
What is the command to view zombie processes if you have Linux virtual box?
You can use the ps aux command to view all processes in the system (including zombie processes), and the STAT column will be equal to Z if the process is a zombie. An example output would be:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
daniel 1000 0.0 0.0 0 0 ?? Z 17:15 0:00 command
How do you know (and) where to put the "wait()" statement to kill
zombie processes?
You can register a signal handler for SIGCHLD that sets a global volatile sig_atomic_t flag = 0 variable to 1. Then, at some convenient place in your program, test whether flag is set to 1, and, if so, set it back to 0 and afterwards (for otherwise you might miss a signal) call waitpid(-1, NULL, WNOHANG) in a loop until it tells you that no more processes are to be waited for. Note that the signal will interrupt system calls with EINTR, which is a good condition to check for the value of flag. If you use an indefinitely blocking system call like select(), you might want to specify a timeout after which you check for flag, since otherwise you might miss a signal that was raised after your last waitpid() call but before entering the indefinitely blocking system call. An alternative to this kludge is to use pselect().
Use:
ps -e -opid,ppid,pgid,stat,etime,cmd | grep defunct
to see your zombies, also the ppid and pgid to see the parent ID and process group ID. The etime to see the elapsed (cpu) time your zombie has been alive. The parent ID is useful to send custom signals to the parent process.
If the parent process is right coded to catch and handle the SIGCHLD signal, and to what expected (i.e., wait/reap the zombies), then you can submit:
kill -CHLD <parent_pid>
to tell the parent to reap all their zombies.

Execute background process and check status from parent

I'm currently trying to:
Execute a background process with a fork() call and execvp() inside the children.
If the call to execvp() was successful, adding the PID of the child process to a list.
If the call to execvp() returned -1 (error), do not add the PID to the list.
My problem is: if execvp() returns -1 (for instance, if the executable isn't found) I can't "communicate" with the parent proccess since I'm inside the child process in the fork(). And if I use waitpid() to wait for the child, I'm not running a background process (since I lose the concurrency).
I tried using WNOHANG and checking *status with (WEXITSTATUS(status) == 1) but it doesn't work (since the parent process executes "instantly" and doesn't know if the child has exited yet, or that's what I think)
My current code:
void background(char *vector[]) {
pid_t childp;
int status;
childp=fork();
if (childp==-1){
perror("Error using fork \n");
return;
}
if (childp==0) { //Child process
if (execvp(vector[0],vector)==-1) {
perror("exec");
exit(1);
}
}
waitpid(-1, &status, WNOHANG);
if(WIFEXITED(status)) {
//Child exited
if (WEXITSTATUS(status) == 1) {
//Child exited with error
return;
}
}
if (insertProcess(childp,vector)==-1)
perror("Full list");
else
updateList();
}
The only solution I've found at the moment is inserting a sleep(1) call before waitpid (Source: https://stackoverflow.com/a/26617152/1339354 ), but this looks more like a hack than something well done. Any other ideas?
If you are using waitpid() with WNOHANG, be sure to especify the child process. If you don't, waitpid() returns status of the last child dead.
I'm not sure if you are trying to save on a list all process that was success. If you are trying it, why not instert always and then delete the process when they die? Control the signal SIGCHLD. In that, use the waitpid for look what process died and delete it in the list. Just deactivate the signal SIGCHLD when you create the process, insert the process on the list and then active again the signal.

Parent and child of fork() in C

Since each process is doing its own thing, which to me feels more like a "brothers/sisters" relationship. Is there a specific reason behind calling them parent process and child process?
Also, is it true that the parent process always run before the child process?
The parent owns the process group and thus spawns and reaps the children. Usually this process does a little bit of administrative work, while the children act as peers and siblings.
The naming is just convention for describing which process spawned the other, though.
The parent process and child process does the work based on your code but not because of parent or child relationship. When you execute fork() in the main thread it will create a child process, here the fork returns a value which is different in parent process and child process which can be used to differentiate the work of parent and child processes accordingly.
fork() always return pid of child in parent process and 0 in child process.
Coming to your second question it always depends on the scheduler as soon as the fork() is called and we cannot predict which process gets to run first after fork() function call.
Is there a specific reason behind calling them parent process and child process?
Well, since it one process (the parent) that creates the second one (the child), that might be the reasoning for the naming.
Also, is it true that the parent process always run before the child process?
The short answer. Nope.
I have been using this in all of my C-code
pid_t pid = fork();
if(pid == 0){ // child
// Child stuff
}else{ // parent
// Parent stuff
}
You might also want to use the
waitpid(pid, NULL, 0);
Parents are always before child. Sort and sweet!!!
fork() creates a copy of the current process which is a part of the process control group. The new process is subordinate to the originating process, for example when a child process dies, SIGCHLD is sent to the parent. Also, the clone is an inferior copy: for instance, any stored getpid() results will be inaccurate in the child; the child has a different parentid, the child has copies of the parent's file descriptors, and has independent resource usage counters.
The parent process, then, is always the one that made the call to fork(), if that's what you mean by run first. If you mean "will the scheduler always give the parent process slices first" then the answer is no.
See: http://gauss.ececs.uc.edu/Courses/c694/lectures/ForksThreads/forks.html, http://linux.die.net/man/2/fork
#include <stdio.h>
#include <unistd.h>
int main(int argc, const char* argv[])
{
pid_t otherPid;
printf("parent pid = %u\n", getpid());
otherPid = fork();
// in the parent, otherPid = the child's (new) process ID
// in the child, otherPid = 0.
switch (otherPid) {
case -1:
printf("Fork failed: %d\n", errno);
return errno;
break;
case 0: // child
sleep(2);
printf("child: my pid is %u\n", getpid());
break;
default:
printf("parent: pid is %u, child should have %u\n", getpid(), otherPid);
sleep(3);
break;
}
return 0;
}

Using fork() in C?

I have been asked this question for homework, and am having trouble figuring it out. If anyone can help me i would really appreciate it.
What Linux library function is like a fork(), but the parent process is terminated?
I'm fairly certain that whoever assigned you this homework is looking for the exec() family of functions, from the POSIX API header <unistd.h>, because there is nothing else that more closely resembles the sort of functionality you describe.
The exec() family of functions executes a new process and replaces the currently running process address space with the newly executed process.
From the man page:
The exec() family of functions replaces the current process image with
a new process image.
It's not exactly the same as "terminating" the parent process, but in practice it results in a similar situation where the parent process address space is erased (replaced) with the address space of the child process.
What Linux library function is like a fork(), but the parent process
is terminated?
The parent process should not terminate because , it must wait for the child processes to finish executing , after which they will be in a state called "zombie state", now it is the responsibility of the parent to clean up the leftovers of the child process. The parent process can terminate without cleaning up the child processes, but then, it is not a proper way to do it, as the exit status of the child processes should be collected and checked by the parent process.
Here is an example, to demonstrate , what i just said...
#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>
int main()
{
pid_t cpid = 1 ;
int status;
cpid = fork();
// Load a application to the child using execl() , and finish the job
printf("Parent waiting for child to terminate\n");
int wait_stat = waitpid(-1,&status,0); // Parent will hang here till all child processes finish executing..
if (wait_stat < 0)
{
perror("waitpid error");
exit(-1);
}
// WIFEXITED and WEXITSTATUS are macros to get exit status information, of the child process
if (WIFEXITED (status))
{
printf("Child of id %u cleaned up\n",wait_stat);
printf("Exit status of application = %u\n",WEXITSTATUS(status));
}
}

What is the difference between fork()!=0 and !fork() in process creation

Currently, I am doing some exercises on operating system based on UNIX. I have used the fork() system call to create a child process and the code snippet is as follows :
if(!fork())
{
printf("I am parent process.\n");
}
else
printf("I am child process.\n");
And this program first executes the child process and then parent process.
But, when I replace if(!fork()) by if(fork()!=0) then the parent block and then child block executes.Here my question is - does the result should be the same in both cases or there is some reason behind this? Thanks in advance!!
There is no guaranteed order of execution.
However, if(!fork()) and if(fork()!=0) do give opposite results logically: if fork() returns zero, then !fork() is true whilst fork()!=0 is false.
Also, from the man page for fork():
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 the correct check is
pid_t pid = fork();
if(pid == -1) {
// ERROR in PARENT
} else if(pid == 0) {
// CHILD process
} else {
// PARENT process, and the child has ID pid
}
EDIT: As Wyzard says, you should definitely make sure you make use of pid later as well. (Also, fixed the type to be pid_t instead of int.)
You shouldn't really use either of those, because when the child finishes, it'll remain as a zombie until the parent finishes too. You should either capture the child's pid in a variable and use it to retrieve the child's exit status:
pid_t child_pid = fork();
if (child_pid == -1)
{
// Fork failed, check errno
}
else if (child_pid)
{
// Do parent stuff...
int status;
waitpid(child_pid, &status, 0);
}
else
{
// Child stuff
}
or you should use the "double-fork trick" to dissociate the child from the parent, so that the child won't remain as a zombie waiting for the parent to retrieve its exit status.
Also, you can't rely on the child executing before the parent after a fork. You have two processes, running concurrently, with no guarantee about relative order of execution. They may take turns, or they may run simultaneously on different CPU cores.
The order in which the parent and child get to their respective printf() statements is undefined. It is likely that if you were to repeat your tests a large number of times, the results would be similar for both, in that for either version there would be times that the parent prints first and times the parent prints last.
!fork() and fork() == 0 both behave in the same way.
The condition itself cannot be the reason the execution sequence is any different.
The process is replicated, which means that child is now competing with parent for resources, including CPU. It is the OS scheduler that decides which process will get the CPU.
The sequence in which child and parent processes are being execute is determined by the scheduler. It determines when and for how long each process is being executed by the processor. So the sequence of the output may vary for one and the same program code. It is purely coincidental that the change in the source code led to the change of the output sequence.
By the way, your printf's should be just the other way round: if fork() returns 0, it's the child, not the parent process.
See code example at http://en.wikipedia.org/wiki/Fork_%28operating_system%29. The German version of this article (http://de.wikipedia.org/wiki/Fork_%28Unix%29) contains a sample output and a short discusion about operation sequence.

Resources