Discussion:
[stunnel-users] Possible signal handling bug in fork mode
(too old to reply)
Philippe Anctil
2016-02-16 16:45:39 UTC
Permalink
Hi,

In fork mode, sending a sigterm signal to a child is caught by the parent.
I suspect it has something to do with signal_pipe being shared by the child
and parent after the fork.

Here I sent a signal to the parent while a child process was also running.
The parent shut down as expected. After sending sigterm, the child remains.

Processes before sigterm:

UID PID PPID C STIME TTY STAT TIME CMD
user 1423 1 0 10:32 ? Ss 0:00
/usr/local/stunnel/bin/stunnel.bin /usr/local/stunnel/etc/server.conf
user 1921 1423 0 10:37 ? S 0:00 \_
/usr/local/stunnel/bin/stunnel.bin /usr/local/stunnel/etc/server.conf

selected pid 1423

Processes after:

UID PID PPID C STIME TTY STAT TIME CMD
user 1921 1 0 10:37 ? S 0:00
/usr/local/stunnel/bin/stunnel.bin /usr/local/stunnel/etc/server.conf

Here I sent the signal to the child. The parent shut down and the child
completed normally.

Processes before:

UID PID PPID C STIME TTY STAT TIME CMD
user 1276 1 0 10:31 ? Ss 0:00
/usr/local/stunnel/bin/stunnel.bin /usr/local/stunnel/etc/server.conf
user 1309 1276 0 10:31 ? S 0:00 \_
/usr/local/stunnel/bin/stunnel.bin /usr/local/stunnel/etc/server.conf

selected pid 1309

Processes after:

UID PID PPID C STIME TTY STAT TIME CMD
user 1309 1 0 10:31 ? S 0:00
/usr/local/stunnel/bin/stunnel.bin /usr/local/stunnel/etc/server.conf

I know I should be trying threads. I will eventually. I can only switch
once I validate it can sustain our level of traffic. Fork has done that
flawlessly for many years now.

Best regards,
--
Philippe Anctil
Philippe Anctil
2016-02-17 23:36:41 UTC
Permalink
Hi,

I have looked further into this issue. Part of the solution would be to
reset signal disposition to SIG_DFL, either in the child after the fork, or
around the call to create_client in accept connection for the child to
inherit appropriate disposition from the start. Temporarily blocking
signals could help. I have to verify exactly how it behaves.

By the way, why is SIG_CHLD set to null_handler in create_client? The
default disposition for this signal is SIG_IGN.

Regards,
Post by Philippe Anctil
Hi,
In fork mode, sending a sigterm signal to a child is caught by the parent.
I suspect it has something to do with signal_pipe being shared by the child
and parent after the fork.
Here I sent a signal to the parent while a child process was also running.
The parent shut down as expected. After sending sigterm, the child remains.
UID PID PPID C STIME TTY STAT TIME CMD
user 1423 1 0 10:32 ? Ss 0:00
/usr/local/stunnel/bin/stunnel.bin /usr/local/stunnel/etc/server.conf
user 1921 1423 0 10:37 ? S 0:00 \_
/usr/local/stunnel/bin/stunnel.bin /usr/local/stunnel/etc/server.conf
selected pid 1423
UID PID PPID C STIME TTY STAT TIME CMD
user 1921 1 0 10:37 ? S 0:00
/usr/local/stunnel/bin/stunnel.bin /usr/local/stunnel/etc/server.conf
Here I sent the signal to the child. The parent shut down and the child
completed normally.
UID PID PPID C STIME TTY STAT TIME CMD
user 1276 1 0 10:31 ? Ss 0:00
/usr/local/stunnel/bin/stunnel.bin /usr/local/stunnel/etc/server.conf
user 1309 1276 0 10:31 ? S 0:00 \_
/usr/local/stunnel/bin/stunnel.bin /usr/local/stunnel/etc/server.conf
selected pid 1309
UID PID PPID C STIME TTY STAT TIME CMD
user 1309 1 0 10:31 ? S 0:00
/usr/local/stunnel/bin/stunnel.bin /usr/local/stunnel/etc/server.conf
I know I should be trying threads. I will eventually. I can only switch
once I validate it can sustain our level of traffic. Fork has done that
flawlessly for many years now.
Best regards,
--
Philippe Anctil
--
Philippe Anctil
Philippe Anctil
2016-02-18 15:52:55 UTC
Permalink
I am proposing the following patch.

Signal blocking effectively prevents signals from being processed by the
child before it has the time to change disposition.

I re-ran my test script and the result is now correct. Signals sent to
child are no longer caught by parent.

With a small program I also tested what happens with pended signals if
their disposition is changed before they're delivered. They're simply
delivered according to the new disposition. Example. If a SIGTERM is sent
to the child right after the fork, the signal will be pended. The child
will then change the signal disposition to SIG_DFL (terminate). When the
child unblocks the signals, SIGTERM is delivered to the child and the child
terminates.

Additional notes from http://man7.org/linux/man-pages/man7/signal.7.html:
- A child created via fork(2) inherits a copy of its parent's signal mask;
the signal mask is preserved across execve(2).
- A child created via fork(2) initially has an empty pending signal set;
the pending signal set is preserved across an execve(2).

All this is on RHEL5.11.

Regards,
Post by Philippe Anctil
Hi,
I have looked further into this issue. Part of the solution would be to
reset signal disposition to SIG_DFL, either in the child after the fork, or
around the call to create_client in accept connection for the child to
inherit appropriate disposition from the start. Temporarily blocking
signals could help. I have to verify exactly how it behaves.
By the way, why is SIG_CHLD set to null_handler in create_client? The
default disposition for this signal is SIG_IGN.
Regards,
Post by Philippe Anctil
Hi,
In fork mode, sending a sigterm signal to a child is caught by the
parent. I suspect it has something to do with signal_pipe being shared by
the child and parent after the fork.
Here I sent a signal to the parent while a child process was also
running. The parent shut down as expected. After sending sigterm, the child
remains.
UID PID PPID C STIME TTY STAT TIME CMD
user 1423 1 0 10:32 ? Ss 0:00
/usr/local/stunnel/bin/stunnel.bin /usr/local/stunnel/etc/server.conf
user 1921 1423 0 10:37 ? S 0:00 \_
/usr/local/stunnel/bin/stunnel.bin /usr/local/stunnel/etc/server.conf
selected pid 1423
UID PID PPID C STIME TTY STAT TIME CMD
user 1921 1 0 10:37 ? S 0:00
/usr/local/stunnel/bin/stunnel.bin /usr/local/stunnel/etc/server.conf
Here I sent the signal to the child. The parent shut down and the child
completed normally.
UID PID PPID C STIME TTY STAT TIME CMD
user 1276 1 0 10:31 ? Ss 0:00
/usr/local/stunnel/bin/stunnel.bin /usr/local/stunnel/etc/server.conf
user 1309 1276 0 10:31 ? S 0:00 \_
/usr/local/stunnel/bin/stunnel.bin /usr/local/stunnel/etc/server.conf
selected pid 1309
UID PID PPID C STIME TTY STAT TIME CMD
user 1309 1 0 10:31 ? S 0:00
/usr/local/stunnel/bin/stunnel.bin /usr/local/stunnel/etc/server.conf
I know I should be trying threads. I will eventually. I can only switch
once I validate it can sustain our level of traffic. Fork has done that
flawlessly for many years now.
Best regards,
--
Philippe Anctil
--
Philippe Anctil
--
Philippe Anctil
Loading...