When using the fork system call, I have seen that many a times that the parent calls waitpid so that the child can finish.
My question here is does the child send a notification to the parent preocess. Without using any shared resource, how can a parent identify that the chils has been completed?
The OS sends a SIGCHLD to the parent when the child exits. You can choose to poll waitpid() using WNOHANG, or to just check with wait() after receiving a SIGCHLD. The child process doesn't need to do anything in particular, this is all managed by the OS.
In Linux Operating system, every child is having some parent and even if the parent dies before the child, the child is inherited by init(PID:1) process. This thing is done so that there should not any zombie process(process entry is there in the process table but process is actually already died) which is taking memory space for no use.
The kernel keeps an eye on all the processes which are died either due to their complete execution or due to some other reason(like invalid memory access) and retains some information like child's exit status. When the child terminates a SIGCHLD signal is sent to the parent. By default the signal is simply ignored. However commonly wait() system call implemented in a handler for the SIGCHLD, so that the parent may act upon the exit status of the child.
In addition to receiving SIGCHLD as mentioned by Erik, you can poll the child for events of interest by using WNOHANG. Here's an example:
pid_t pid = fork();
if (pid) {
while (1) {
int status;
int waitpid(pid, &status, WNOHANG);
if (pid == waitpid && WIFEXITED(status))
break;
// do other stuff
}
}
Related
I am writing a server. It uses fork() to create new child processes. I want to kill the child processes when a parent process dies. I am planning to use an array to store the pids of the child processes.But there is chance that the child process might terminate before the parent process. In this case if we call kill function using SIGKILL and pid of the child process that already terminated, will it throw an exception?
When a child process terminates, a SIGCHLD signal is sent to the parent. You can handle this signal in the parent to check what child has terminated on it's own, before you got a chance to wait for it. And you should wait() for all children to avoid zombie processes.
You can also take a look at this thread for an alternative way to have the children terminate when the parent terminats: How to make child process die after parent exits?
Parent process launches a child process by invoking CreateProcess() method which returns immediately even before the child process is initialized. How do I make the parent process wait until the Child process got initialized and started executing? WaitForSingleObject() call makes the parent process to wait until the child thread terminates or until timeout.
Is there any similar method which makes the parent process to wait until the child process is intialized?
You can create a named event in WinAPI in the parent process and set it to unsignalled state. Call WaitForSingleObject on the event handle. Then in the child process you can open event by name and signal it (call SetEvent()) after the child process is initialized.
If you are using threads, one of the simpliest way to make parent thread wait until the child finishes is using .join() function. In the parent process's end use
child.join();
I'm writing this with c++ on Ubuntu 12.04 LTS and i am explicitly not using any BOOST libraries.
What I want to do is have a parent process and two or more children run simultaneously.
The parent process acts like an event listener and task dispatcher. The children handle the tasks the parents tells them to; these tasks are system calls, and the parent doesn't care when they finish.
What I have done successfully so far is
parent will fork() some children and retain their pids
children are suspended (S) immediately after being fork() with pause()
parent resumes (R) and detects events in a standard event loop way
what I need to know next is how to resume a child and return to the parent while child is still running.
So my questions are, can a parent and child run simultaneously and safely in this manner? (where the parent doesn't care what the child is doing after its resumed)
What do I have to do to in general to resume a child process after a pause()?
below is the constructor function that forks the children
childManager(int number_of_children, pid_t parent) {
int i=0;
while(number_of_children--) {
if(parent == getpid())
{
this->parent = parent;
children.push_back({++i,_IDLE,fork()});
if(parent != getpid()) pause();
}
}
}
The only question I see here is
What do I have to do to in general to resume a child process after a pause()?
Send it a signal whose action is either to execute a signal-catching function or terminate the process. For example:
kill(children[i], SIGUSR);
That said, this is a less than ideal way to do this. You could just as easily have the children block on a pipe waiting for the parent to tell them to do something. Or about 30 similar things which don't involve signals.
To answer your specific questions:
So my questions are, can a parent and child run simultaneously and safely in this manner? (where the parent doesn't care what the child is doing after its resumed)
The parent process will have to call wait or waitpid to harvest the child processes after they exit. If you do not do that you will be left with zombie processes. You can do this in a nonblocking way inside your event loop in the parent process.
What do I have to do to in general to resume a child process after a pause()?
You have to send a signal to the child process. You do this by calling kill in the parent process. You will need to install a signal handler in the child process to catch the signal - use sigaction for that.
I'm creating a simple shell in linux and I'm having trouble getting a command to run in the background.
here is my code so far:
create command,argv and check if it is to be ran in the background &
enter this code:
if(strcmp(command,"cd")==0)
{
chdir(argv[1]);
}
else if(strcmp(command,"clr") == 0)
{
if ((pid = fork()) == 0)
{
execvp("clear",argv);
}
wait(&status);
}
else
{
if ((pid = fork()) == 0)
{
execvp( prog, argv );
}
wait(&status);
}
command and argv are what I get from the user.
I need to run a command in the background if '&' is the last part of the command. I have already checked for that with a boolean var of bg. but I'm having trouble with the WAITPID() function im not sure where it goes.
I guess your issue is if you end up calling waitpid() directly, you will block, and the process is not really running in the background. You can handle this in two ways.
Choice 1: Avoid the issue. After calling fork once, have the child fork one more time. Let the grandchild execute the command, and let the child exit. The parent waits on the child like before, but the grandchild is executing the command in the background. The grandchild process will be reaped by the init process.
Choice 2: Notice the asynchronous notification that the child is done. When a child process dies, the parent process will receive the SIGCHLD signal. Have a signal handler notice this signal and reap the child. This might require that you restructure your code so that the synchronous waiters actually receive a synchronous notification from your signal handler. You would then need a mechanism for the signal handler to distinguish between foreground and background children, and only send synchronous notifications for the foreground children.
I am trying to create a child process and then send SIGINT to the child without terminating the parent. I tried this:
pid=fork();
if (!pid)
{
setpgrp();
cout<<"waiting...\n";
while(1);
}
else
{
cout<<"parent";
wait(NULL);
}
but when I hit C-c both process were terminated
Don't use CTRL-C, this sends a signal to all processes with the same controlling terminal (ie, in the same session). That's something that setpgid doesn't change though I think there's a setsid (set session ID) call for that purpose.
The easiest solution is simply to target the specific process rather than a session. From the command line:
kill -INT pid
From C:
kill (pid, SIGINT);
where pid is the process ID you want to send the signal to.
The parent can get the relevant PID from the return value from fork(). If a child wants its own PID, it can call getpid().
Aha, the mystery of process groups and sessions and process group leaders and session group leaders appears again.
Your control/C sent the signal to a group. You need to signal an individual pid, so follow paxdiablo's instructions or signal ("kill") the child from the parent. And don't busy wait! Put a sleep(1) in the loop, or better yet, one of the wait(2) system calls.
You could try implementing a SIGINT signal handler which, if a child process is running, kills the child process (and if not, shuts down the application).
Alternatively, set the parent's SIGINT handler to SIG_IGN and the child's to SIG_DFL.