http://www.perlmonks.org?node_id=820318

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

I am having trouble that my script should change a shared variable based on a signal. The signal is caught and the shared variable is changed, but the program does automatically stop. See below some a small piece of code as an example. I am using Perl 5.10.0 and CentOS 4.
use threads; use threads::shared; $SIG{'HUP'}='switchFlag'; $flag::shared; my $thr=threads->new(\&printer); $thr->detach(); sleep 10000; print "I am here\n"; exit; sub printer{ while(1) { sleep 1; print "Shared: $flag\n"; } } sub switchFlag{ $flag=!$flag; print "signal caught"; $SIG{'HUP'}='switchFlag'; }
Update: Same behaviour with Perl 5.8 under Solaris 10...

Replies are listed 'Best First'.
Re: Catching signals under Linux
by dave_the_m (Monsignor) on Jan 29, 2010 at 16:59 UTC
    You have two issues. First, by $flag::shared;, I think you actually meant my $flag : shared;; i.e. you weren't actually creating a shared variable.

    Second, if the signal gets delivered to the parent thread, then that will wake it up from its sleep, so you'll want something like sleep 10000 while 1 to keep it alive.

    Dave.

Re: Catching signals under Linux
by 7stud (Deacon) on Jan 29, 2010 at 10:06 UTC

    On a more elementary level, why does this code:

    use strict; use warnings; use 5.010; use threads; sub thr_func { say 'in thread'; $SIG{'HUP'} = sub { say "signal caught" }; } my $thr = threads->create('thr_func'); $thr->kill('HUP')->join();
    produce this output:
    Signal SIGHUP received, but no signal handler set.

    The threads docs seem pretty clear that you can signal a thread.

      Because you're likely to send the signal before the other thread was able to set the handler. Note that your output doesn't include 'in thread', which is printed before you set SIGHUP.

        I have not looked closely at your code, but I would observe that the scenario just described is extremely common, and therefore extremely likely.

        Yup:
        use strict; use warnings; use 5.010; use threads; sub thr_func { say 'in thread'; $SIG{'HUP'} = sub { say "signal caught" }; say 'doing some task...'; sleep 5; } my $thr = threads->create('thr_func'); sleep 2; $thr->kill('HUP')->join(); --output:-- in thread doing some task... signal caught
        Thanks.
Re: Catching signals under Linux
by 7stud (Deacon) on Jan 29, 2010 at 21:32 UTC

    Is this what you want?

    use strict; use warnings; use 5.010; use threads; use threads::shared; my $flag = 0; share($flag); say "\$flag in main() is: $flag"; $SIG{'HUP'} = sub { $flag = !$flag; say "signal caught, \$flag in main() changed to: $flag"; }; sub thr_func { for (1 .. 5) { sleep 1; say "\$flag in thread is: $flag"; } } my $thr = threads->create('thr_func')->detach(); sleep 3; #allow time for thread to be created and start running kill('HUP', $$); #send signal to main() sleep 10; --output:-- $flag in main() is: 0 $flag in thread is: 0 signal caught, $flag in main() changed to: 1 $flag in thread is: 0 $flag in thread is: 1 $flag in thread is: 1 $flag in thread is: 1
Re: Catching signals under Linux
by Anonymous Monk on Jan 29, 2010 at 07:58 UTC
    Which thread caught the signal? Did that thread end?
      I can not really tell, but my guess is that it is the main thread...
        Um, guessing is not allowed :D
        #!/usr/bin/perl -- use strict; use warnings; use threads; use threads::shared; Main(@ARGV); exit(0); sub Main { local $SIG{'HUP'} = 'switchFlag'; share($::flag); $::flag = !!undef; # false my $thr = threads->new( \&printer ); $thr->detach(); sleep 10000; print threads->tid, " is here\n"; } ## end sub Main sub printer { while (1) { sleep 1; print threads->tid, " Shared: $::flag\n"; } } ## end sub printer sub switchFlag { $::flag = !$::flag; print threads->tid, " caught signal\n"; $SIG{'HUP'} = 'switchFlag'; }