Handle and propogate SIGHUP signal to child process without parent termination - linux

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.

Related

How do I learn about unknown children exiting in Go on Unix/Liunx?

It doesn't look like Go has a way to register a signal handler, so I can't catch SIGCHLD. So, how do I learn about a process exiting that I may not known about because my process has its CHILD_SUBREAPER flag set or is PID 1 in a PID namespace.
You can register signal handlers using signal.Notify

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.

Signal handling: printing something and then taking the default behaviour

My requirement is that whenever a program terminates in any way other than its normal completion [i.e. exit() system call at the end], I need to handle it (say, hook a print "Hello" statement) before it actually terminates.
For example, when I hit Ctrl+C while running a program, it should print Hello and continue the way a SIGINT must have been handled.
If I use my custom signal handler function (having a print statement logic) in my source code, it would alter the default behavior i.e. how SIGINT would have ideally terminated.
1) Can anyone help me achieve both of this? What other signals I need to handle explicitly (maybe SIGTERM ?) which can cause termination of a running process?
2) How can I generate/test them ?(say, SIGINT can be generated by hitting Ctrl + C in linux)
there are several signals supported in unix/linux.
Except SIGKILL, SIGSTOP, all others can be interpreted and handled.
process of registering the handler to a particular signumber should be same.
We can use kill command to send signals to other process.
For example: it sends TERM signal to processid 1234
kill -s TERM 1234
The sigaction(2) man page has some useful info. For one thing, every signal but SIGKILL and SIGSTOP can be caught.
In your signal handler, you have two options:
puts(3) and then manually do something (exit() or raise(SIGSTOP) or something).
puts(3) and then try to get the default signal behaviour by setting the handler back to SIG_DFL, and sending the signal to yourself with raise(3). I'm not sure whether you can just sigaction() to restore your signal handler right after raise() from inside that signal handler, and whether that would be portable even if it happens to work on Linux.
List all signals with kill -l
Send a signal with kill -INT 1234, or in the shell you started a background process from: kill -INT %1. Or to avoid copy/pasting a PID every time: pkill -INT process_name (pkill and pgrep are related.)

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 :)

nodejs child process signal handling

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

Resources