Since you haven't shown your code for how you're handling the signals, I can only hazard a guess. The OS SIGUSR1 comes to each child process' main thread (because that's how it works). Then the child process in turn does a $thread->kill() on each of your threads. So far so good?
See threads:
sending a signal to a thread does not disrupt the operation the thread is currently working on: The signal will be acted upon after the current operation has completed. For instance, if the thread is stuck on an I/O call, sending it a signal will not cause the I/O call to be interrupted such that the signal is acted up immediately.
The good news is, there's a simple answer to the question of how to send signals to threads: don't. It's unreliable at best, and even if it worked, your threads would be in random states. Instead, instrument your threads with their own timeouts (if they're doing blocking operations, that's really where the timeouts belong anyway), and have the threads poll a threads::shared $shutdown variable that's set by your signal handler. Provided you have reasonable timeouts and don't just busy-wait, this is a reasonable use of polling. With the above caveat, remember your child program's main application flow is a thread, too, and subject to the same limitations. When the signal comes in, you give all the threads a few seconds to exit, and if there are still any running, you detach them and exit with a warning.
bash $ (sleep 1; killall -HUP the_parent) & perl threads.pl
[1] 4842
Thread 1: Created
Thread 2: Created
Thread 3: Created
Shutting down 3 threads
Thread 1: Shutting down
Thread 3: Shutting down
1 still running. Giving up!
#!/usr/bin/env perl
use 5.012;
use warnings FATAL => 'all';
use autodie;
if (my $pid = fork) {
$0 = 'the_parent';
local $SIG{HUP} = sub { kill USR1 => $pid };
exit(0 < waitpid $pid,0);
}
$0 = 'the_child';
use threads;
use threads::shared;
my $shutdown :shared = 0;
my @thr = map { threads->create(sub {
printf "Thread %d: Created\n", threads->tid;
sleep 1 + rand 2 until $shutdown;
printf "Thread %d: Shutting down\n", threads->tid;
lock($shutdown); cond_signal($shutdown);
}) } 1..3;
$SIG{USR1} = sub { $shutdown = 1 };
sleep until $shutdown;
say "Shutting down " . scalar threads->list . " threads";
my $until = 1 + time; # Wait this many seconds before abort
while (my $threads = threads->list(threads::running)) {
lock($shutdown);
cond_timedwait($shutdown, $until) or last;
}
if (my @remain = threads->list(threads::running)) {
$_->detach for @remain;
$_->join for threads->list(threads::joinable);
die scalar @remain . " still running. Giving up!\n";
}
$_->join for @thr;
say "All threads exited normally.";
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.
|