in reply to killing threads inside forks
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.";
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: killing threads inside forks
by mojo2405 (Acolyte) on Jul 31, 2013 at 14:45 UTC | |
by rjt (Curate) on Jul 31, 2013 at 20:52 UTC | |
by mojo2405 (Acolyte) on Aug 01, 2013 at 07:43 UTC | |
by BrowserUk (Patriarch) on Aug 01, 2013 at 08:43 UTC | |
by mojo2405 (Acolyte) on Aug 01, 2013 at 13:59 UTC | |
|