nodejs child process signal handling - node.js

I'v got a daemon child process (Linux) spawned from the server via child_process.spawn(...).
I can kill it with p.kill() command and the child process dies fine.
However, when I send USR signals to the child process - let's say p.kill("SIGUSR1") - prior to killing it p.kill("SIGKILL") the child process gets the USR1 signal, but, surprisingly, the subsequent SIGKILL never gets to the child(!?). Also, exit event of the child process is not called as well.
Is there anything I miss about signal handling in node?
Cheers

Have just found it :) It's a bug: https://github.com/joyent/node/issues/1035
Calling process.kill(pid,signal) works multiple times.
Cheers

Related

Handle and propogate SIGHUP signal to child process without parent termination

I've got a piece of classic problem, but can't figure out how to deal with it. There is a bash process which executes children, and I want to send some signal to it (SIGHUP), handle it there and propagate this signal to one of the children (another_long_running_process for example). Here is snippet:
#!/bin/bash
long_running_process &
another_long_running_process &
pid=$!
trap 'kill -1 $pid' HUP
wait $pid
Ok, now I setup trap, create handler to send signal to particular pid, but then find out that my script just exits after first SIGHUP receiving and handling. The problem that bash returns immediately from wait built-in:
When Bash receives a signal for which a trap has been set while waiting for a command to complete, the trap will not be executed until the command completes. When Bash is waiting for an asynchronous command via the wait built-in, the reception of a signal for which a trap has been set will cause the wait built-in to return immediately with an exit status greater than 128, immediately after which the trap is executed.
And yes, my script just exits after first time I send SIGHUP, by design. But I need to keep it running.
And I can't figure out how to wait children processes, and propagate one of them (ok, even all of them) SIGHUP signals multiple times while they're running. Is this achievable in such problem definition? I think with parent pid I can iterate over children and find required process and then send signal particularly there, but it looks a bit overengineering, or not?
Ok, finally I fix my problem with following approach: I setup ignore signal handler in bash-script and make it leader of process group. Then redefine SIGHUP handler in another_long_running_process and then send signal to process group. So bash-script and long_running_process ignore that signal, and another_long_running_process catch signal and handle it.

Bash wait on child process can return even when child process is still running

I have a shell script which spawns a child process in the background and waits on it(via wait command) . It also catches SIGTERM and passes it to the child. But whenever I send a SIGTERM to the parent process it comes out of the "wait" even though the child is still running(child catches SIGTERM) . Is it possible to achieve truly waiting on a child from inside a shell script until the child dies?
This is explicit behavior which common idiom depends on. Observe the following difference:
# this waits 10 seconds, and doesn't handle signal handlers until later
sleep 10
# this returns immediately when a signal is received
sleep 10 & wait $!
You're perfectly able to check whether remaining background tasks exist and wait again:
sleep 10 & pid=$!
while kill -0 "$pid"; do wait "$pid"; done
For a full discussion of signal handling, including the behavior described here, see SignalTrap.

NodeJS child processes are terminated on SIGINT

Im creating NodeJS application, that creates quite a few child processes. They are started by both spawn and exec (based on lib implementation). Some examples may be GraphicsMagick (gm) for image manipulation or Tesseract (node-tesseract) for OCR. Now I would like to gracefully end my application so I created shutdown hook:
function exitHandler() {
killer.waitForShutdown().then(function(){
logger.logInfo("Exited successfully.");
process.exit();
}).catch(function(err) {
logger.logError(err, "Error during server shutdown.");
process.exit();
});
}
process.on('exit', exitHandler);
process.on('SIGINT', exitHandler);
process.on('SIGTERM', exitHandler);
Exit handling itself works fine, it is waiting well and so on, but there is a catch. All "native" (gm, tesseract, ...) processes that run at that time are also killed. Exception messages only consists of "Command failed" and then content of command which failed e.g.
"Command failed: /bin/sh -c tesseract tempfiles/W1KwFSdz7MKdJQQnUifQFKdfTRDvBF4VkdJgEvxZGITng7JZWcyPYw6imrw8JFVv/ocr_0.png /tmp/node-tesseract-49073e55-0ef6-482d-8e73-1d70161ce91a -l eng -psm 3\nTesseract Open Source OCR Engine v3.03 with Leptonica"
So at least for me, they do not tell anything useful. I'm also queuing process execution, so PC don't get overloaded by 50 processes at one time. When running processes are killed by SIGINT, new processes that were queued are started just fine and finishes successfully. I have problem only with those few running at the time of receiving SIGINT. This behavior is same on Linux (Debian 8) and Windows (W10). From what I read here, people usually have opposite problem (to kill child processes). I tried to search if stdin gets somehow piped into child processes but I can't find it. So is this how its supposed to work? Is there any trick to prevent this behavior?
The reason this happens is because, by default, the detached option is set to false. If detached is false, the signals will also be sent to the child processes, regardless of whether you setup an event listener.
To stop this happening, you need to change your spawn calls to use the third argument in order to specify detached; for example:
spawn('ls', ['-l'], { detached: true })
From the Node documentation:
On Windows, setting options.detached to true makes it possible for the
child process to continue running after the parent exits. The child
will have its own console window. Once enabled for a child process, it
cannot be disabled.
On non-Windows platforms, if options.detached is set to true, the
child process will be made the leader of a new process group and
session. Note that child processes may continue running after the
parent exits regardless of whether they are detached or not. See
setsid(2) for more information.

parent process and child process relationship in Linux bash script

i have a question about linux process, and i can not figure it out.
This problem came from the book “Advanced Bash Script”, code is here: (I have simplified it)
#! /bin/bash
# spawn.sh
sleep 1
sh $0 # fork a child process here and into infinite loop
exit 0 # the script will never come here
when i run ./spawn.sh in the shell, the process will be stuck there, and there will be a lot of "sh spawn.sh" processes there after a while.
i think the relationship among processes now is like:
./spawn.sh process(pid: 10000) ---> child process(pid: 10001) ---> child process(pid:1002) --->child process(pid:1003) ---> and so on
when i push Control-C in the Shell, the parent process is over, and all its child processes are over too. this is where i can not understand. why all child processed perish ? i think the relationship among processes should be like:
init(pid: 1) ---> child process(pid: 10001) ---> child process(pid:1002) --->child process(pid:1003) ---> and so on
But the fact is that as if parent process sends a signal to it child process when it is over, thus cause all child processes perish one by one. Is this normal or a feature of shell script?
thank you very much in advance.
when i push Control-C in the Shell, the parent process is over, and
all its child processes are over too. this is where i can not
understand. why all child processed perish
When you hit Ctrl-C, SIGINT is sent not only to the parent process but to the entire process group. What this means is that all three processes get a SIGINT, so they die. To see this in action, add a
trap "process $$ exiting" INT
A quick way to see that children don't react to their parents' demise is to have a script spawn a single child and then kill the parent.
Control-C is killing the most recent child, not the original shell. When sh $0 exits, the next line of code causes the current shell to exit as well, which causes a cascade of completed processes all the way back to the original parent.
i think i know the answer now. it is because that Control-C will send SIGINT to not only the shell script process, but also its sub processes. Since these processes do not trap SIGINT, so they are over.
Command kill -2 is not the same as Ctrl-C, for detail, see this: http://ajhaupt.blogspot.com/2011/01/whats-difference-between-ctrl-c-and.html
And thank you all guys help me :)

How can a process kill itself?

#include<stdlib.h>
#include<unistd.h>
#include<signal.h>
int main(){
pid_t pid = fork();
if(pid==0){
system("watch ls");
}
else{
sleep(5);
killpg(getpid(),SIGTERM); //to kill the complete process tree.
}
return 0;
}
Terminal:
anirudh#anirudh-Aspire-5920:~/Desktop/testing$ gcc test.c
anirudh#anirudh-Aspire-5920:~/Desktop/testing$ ./a.out
Terminated
for the first 5 secs the output of the "watch ls" is shown and then it terminates because I send a SIGTERM.
Question: How can a process kills itself ? I have done kill(getpid(),SIGTERM);
My hypothesis:
so during the kill() call the process switches to kernel mode. The kill call sends the SIGTERM to the process and copies it in the process's process table. when the process comes back to user mode it sees the signal in its table and it terminates itself (HOW ? I REALLY DO NOT KNOW )
(I think I am going wrong (may be a blunder) somewhere in my hypothesis ... so Please enlighten me)
This code is actually a stub which I am using to test my other modules of the Project.
Its doing the job for me and I am happy with it but there lies a question in my mind how actually a process kills itself. I want to know the step by step hypothesis.
Thanks in advance
Anirudh Tomer
Your process dies because you are using killpg(), that sends a signal to a process group, not to a process.
When you fork(), the children inherits from the father, among the other things, the process group. From man fork:
* The child's parent process ID is the same as the parent's process ID.
So you kill the parent along with the child.
If you do a simple kill(getpid(), SIGTERM) then the father will kill the child (that is watching ls) and then will peacefully exit.
so during the kill() call the process switches to kernel mode. The kill call sends the SIGTERM to the process and copies it in the process's process table. when the process comes back to user mode it sees the signal in its table and it terminates itself (HOW ? I REALLY DO NOT KNOW )
In Linux, when returning from the kernel mode to the user-space mode the kernel checks if there are any pending signals that can be delivered. If there are some it delivers the signals just before returning to the user-space mode. It can also deliver signals at other times, for example, if a process was blocked on select() and then killed, or when a thread accesses an unmapped memory location.
I think it when it sees the SIGTERM signal in its process tables it first kills its child processes( complete tree since I have called killpg() ) and then it calls exit().
I am still looking for a better answer to this question.
kill(getpid(), SIGKILL); // itself I think
I tested it after a fork with case 0: and it quit regular from separate parent process.
I don't know if this is a standard certification method ....
(I can see from my psensor tool that CPU usage return in 34% like a normal program code with
a counter stopped ) .
This is super-easy in Perl:
{
local $SIG{TERM} = "IGNORE";
kill TERM => -$$;
}
Conversion into C is left as an exercise for the reader.

Resources