How come tini proxies signals to child processes if the sigcgt bits are all 0?
chengdol opened this issue · 1 comments
Hi folks,
Thanks in advance to take a look at my question.
I run tini in my docker container as PID 1 and I see inside the container:
docker run -it --rm <docker with init> bash
cat /proc/1/status | grep -i sig
SigPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000300000
SigCgt: 0000000000000000
I know that in Linux init process is treated specially, in its PID namespace the init process will ignore any signal with default action (not talk about signal sent from parent PID namespace).
The SigCgt is all 0 which means there is no signal handler registered. If so how come tini redirects signal to its child if it does not catch any signal? I think I may misunderstand the relationship between sigcgt
and signal forwarding
, appreciate your kindness to correct me if I am wrong.
The way Tini catches signals is by blocking all signals that should be forwarded to the child, and then waiting for them via sigtimedwait
(https://linux.die.net/man/2/sigtimedwait). The set of signals Tini blocks is all signals save for things like SEGV that would be used by the Kernel to report errors in Tini's execution to Tini itself:
The blocking happens here:
Lines 456 to 499 in 378bbbc
And the waiting happens there:
Lines 501 to 514 in 378bbbc
Now, you might be left wondering why SigBlk is all zeroes if we're supposedly blocking all signals. The answer to that is that while sigtimedwait is executing, the Kernel temporarily unblocks all signals we are waiting on:
As a consequence, if you look at the signals blocked by Tini while Tini is running, then you'll typically see nothing, because most of the time Tini is doing nothing and is just waiting for signals. That said, if you get particularly lucky, you could see a different signal mask if you check the signals while Tini is reaping children.