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


in reply to Re^2: Signals vs. Windows
in thread Signals vs. Windows

Note that your example still uses the devilish signal.

Yes, but in the way it was intended -- as an IPC mechanism, not ITC.

Resolves the blocking I/O by pushing it another thread deeper. Thank you.

Indeed. (Be sure to look at the stack_size parameter to threads.)

But, it isn't actually necessary to go one thread deeper. If your current main/parent thread can attempt to send a signal to its child threads to terminate them, it could also send that signal directly to the processes those child threads are waiting on, thus cutting out the middle man and the need for an extra thread.

All that would be required is to shared the pids of those processes with the parent thread so that it knows where to send the signal when the time is right.

The following script starts 5 asynchronous, piped subprocesses in threads that will each run for 5 seconds producing one 'line' of output per second. The threads share the pids of those processes with the main thread via a shared array indexed by their thread ids.

The main thread then applies timeouts to those processes ranging from 3 to 7 seconds, killing them after the appropriate delay. It then gathers whatever output they had produced before the timeout from the threads by joining them.

You can see -- in the console output after the __END__ -- that the first two processes were terminated (SIGINT) after 3 and 4 seconds respectively and their output was truncated. The other 3 complete their output and terminate normally.

#! perl -slw use strict; use Time::HiRes qw[ sleep time ]; use threads; use threads::shared; my @pids :shared; sub asyncPipedProc { my $tid = threads->tid; my $cmd = shift; $pids[ $tid ] = open my $pipe, '-|', $cmd or die $!; my @input; push @input, $_ while <$pipe>; return @input; } my $cmd = q[ perl -E"$|++; sleep(1), say for 1 .. 5" ]; my @running; for my $timeout ( 3 .. 7 ) { push @running, [ threads->new( \&asyncPipedProc, $cmd, $_ ), time() + $timeout ]; } while( @running and sleep 0.1 ) { for my $i ( reverse 0 .. $#running ) { if( $running[ $i ][ 1 ] < time() ) { kill 2, $pids[ $running[ $i ][ 0 ]->tid ]; printf "From thread %d got:\n%s", $running[ $i ][ 0 ]->tid, join'', $running[ $i ][ 0 ]->join; splice @running, $i, 1; } } } __END__ C:\test>multi-timeout.pl Terminating on signal SIGINT(2) From thread 1 got: 1 2 3 Terminating on signal SIGINT(2) From thread 2 got: 1 2 3 4 From thread 3 got: 1 2 3 4 5 From thread 4 got: 1 2 3 4 5 From thread 5 got: 1 2 3 4 5

With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.

RIP Neil Armstrong