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.
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?
I would like to ask what is the signal that is called when the user logs out? I have a Qt gui app that has handler for SIGTERM and SIGHUP signals. The app also has its own close event handler, so user can't close it by clicking on "X". The problem is that when the user logs out then the ubuntu hangs (the icon from taskbar disappears but the process keeps running) and does not let the user log out because (imo) it waits for the process to be terminated. When I use kill -15 'myapp' command then the app closes normally as it is supposed to so the problem shouldn't be in my handler.
static int setupHandlers(){
struct sigaction hup,term;
hup.sa_handler = signalHandler;
sigemptyset(&hup.sa_mask);
hup.sa_flags = 0;
if (sigaction(SIGHUP, &hup, 0) > 0){
return 1;
}
term.sa_handler = signalHandler;
sigemptyset(&term.sa_mask);
if (sigaction(SIGTERM, &term, 0) > 0){
return 2;
}
return 0;
}
signalHandler just calls exit(0) (also tried _exit(0) and abort())
There are 3 standart terminating signals, that you can handle - SIGINT, SIGQUIT and SIGTERM. Try to subscribe to each one of them and look.
signalHandler just calls exit(0) (also tried _exit(0) and abort())
You rather need to tell Qt to exit. Your signal handler need to have a reference on the application object and call QCoreApplication::exit(0);.
Whether it is by SIGTERM or by the user user input, your application need to nicely handle termination requests. In particular ensure that all objects which launch a process or a thread are cleanly destroyed when it happens. The classic code inspired from QtCreator :
d->m_guiProcess.terminate();
if (!d->m_guiProcess.waitForFinished(1000)) { // This is blocking, so be fast.
d->m_guiProcess.kill();
d->m_guiProcess.waitForFinished();
}
The code executing this need to stop, so it first forward nicely a SIGTERM (terminate), wait for small amount of time and then ask rudely with a SIGKILL (kill).
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.
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
}
}
As part of a Linux benchmark application, I have a parent process that forks multiple children that will each perform a task in parallel. I'm using signals to coordinate between them since I'm looking for as accurate of timing as possible. Each child will prepare for the test, then enter a 'barrier' controlled by the parent via signals.
Once all the children have entered the barrier, the parent records the time stamp, and signals the child processes to begin. As soon as the child finishes each portion of the test they signal the parent before entering the next barrier. The parent is listening for these signals and once it receives them from all of the child processes, it records the completion time(s).
My problem is that the program terminates non-deterministically; the signals don't always get delivered. The signal handler could not be any simpler:
void sig_child_ready (int sig)
{
num_child_ready++;
}
num_child_ready is declared as volatile sig_atomic_t. I've tried using sigprocmask without success in a loop like this:
sigprocmask (SIG_BLOCK, &mask, &oldmask);
while (num_child_ready < num_child)
{
/* waiting for child signals here */
sigsuspend (&oldmask);
}
sigprocmask (SIG_UNBLOCK, &mask, NULL);
I'm not sure how to proceed from here. Am I correct that sigprocmask is needed to 'queue' the signals so they are processed one by one?
Or, consider this hypothetical scenario: the parent receives a signal, is executing its handler, then receives ANOTHER identical signal. Is the signal handler called recursively? ie will it execute the second handler before returning to, and completing the first handler?
I'm just looking to make sure all of the signals are delivered as synchronously as possible.
Normal signals are not queued, and that's likely the cause of your problem.
If one signal arrives before the handler has been run for a past signal, they'll get merged and there's little you can do about that - you're probably better off using some other form of IPC to do this kind of synchronization.
You could use "realtime signals", which do get queued. You'd send signals with sigqueue() and
"receive" them with sigwaitinfo() or establishing a signal handler setting the SA_SIGINFO flag in a struct sigaction