http://qs321.pair.com?node_id=11107096

shulam has asked for the wisdom of the Perl Monks concerning the following question:

I have been debugging a program which uses signals and threads this weekend.

The program goes somewhat like this:

1. Fork a child which sends a "child ready" signal (USR2) to parent after it has done processing a thing.

2. Start a thread in parent, which does things in background while waiting for the child to be ready.

3. Handle the "child ready" signal in parent which indicates the child is ready to proceed to doing another thing.

4. Repeat this until receiving an INT or TERM signal.


Now this works mostly fine. A behaviour, which I don't understand, starts happening when I add a signal handler for INT and TERM, in addition to the "child ready" signal, which is USR2.


I have simulated the program with a code snippet. It starts a child which is constantly sending TERM and USR2 signal to parent.

(TERM signal normally comes from init process, here it comes from the child)

Parent has handlers for both signals AND has a thread which has handlers for both those signals.

I expected the thread signal handlers to never be called, since I don't call threads->kill anywhere.

Here is the code, it outputs a message every time a signal handler is called:

use 5.20.2; use warnings; use threads; use Time::HiRes qw/ usleep /; $SIG{USR2} = 'IGNORE'; $SIG{TERM} = 'IGNORE'; if (fork() == 0) { sleep 1; my $ppid = getppid(); for (1 .. 1000) { usleep(int(rand(100000))); kill 'USR2', $ppid; kill 'TERM', $ppid; } } $SIG{TERM} = sub { say "TERM"; }; $SIG{USR2} = sub { say "USR2"; }; my $thread = threads->create(sub { $SIG{TERM} = sub { say "THREAD TERM"; }; $SIG{USR2} = sub { say "THREAD USR2"; }; sleep 10; threads->exit(); }); sleep 10; while ($thread->is_running()) { usleep 1000; } while (! $thread->is_joinable()) { usleep 1000; } $thread->join();

I get output like this:

USR2 TERM USR2 TERM THREAD USR2 THREAD TERM

The thread signal handlers are not called if I send only one type of signal from child process.

If I comment out one of kill-commands from child code, so that I send only USR2 or TERM, I don't get the thread signal handler output.

It doesn't make a difference if I change the TERM signal to be USR1

Can someone explain why this happens?


Perl version information:

This is perl 5, version 24, subversion 1 (v5.24.1) built for x86_64-li +nux-gnu-thread-multi (with 85 registered patches, see perl -V for more detail)

Running on Debian Linux Stretch