title: Perl trapping Ctrl-C with threads in bash
body: <p>While I see how to have <a href="https://stackoverflow.com/questions/7512317/perl-trapping-ctrl-c-sigint-in-bash">Perl trap Ctrl-C (sigint) in bash</a>; I'm getting lost at why does it fail with threads; I'm trying the following script:</p>
  
  <pre><code>#!/usr/bin/env perl
  
  use threads;
  use threads::shared; # for shared variables
  
  my $cnt :shared = 0;
  
  sub counter() {
    while (1) {
      $cnt++;
      print "thread: $cnt \n";
      sleep 1;
    }
  }
  
  sub finisher{
    ### Thread exit! ...
    print "IIII";
    threads-&gt;exit();
    die;
  };
  
  # any of these will cause stop of reaction to Ctrl-C
  $SIG{INT} = \&amp;finisher;
  $SIG{INT} = sub {print "EEE\n" ;} ;
  $SIG{INT} = 'IGNORE';
  
  # setting to DEFAULT, brings usual behavior back
  #~ $SIG{INT} = 'DEFAULT';
  
  my $mthr = threads-&gt;create(\&amp;counter);
  $mthr-&gt;join();
  </code></pre>
  
  <p>... and as soon as the SIGINT handler is set to anything else than the default (<em>where Ctrl-C causes exit</em>), it basically causes for the script to stop reacting on Ctrl-C any longer:</p>
  
  <pre><code>$ ./test.pl 
  thread: 1 
  ^Cthread: 2 
  ^C^Cthread: 3 
  ^C^C^C^Cthread: 4 
  thread: 5 
  thread: 6 
  thread: 7 
  thread: 8 
  Terminated
  </code></pre>
  
  <p>... and I have to <code>sudo killall perl</code> in order to terminate the script. </p>
  
  <p>There is a bit on threads and Ctrl-C in these links: </p>
  
  <ul>
  <li><a href="http://forums.devshed.com/perl-programming-6/sending-sig-int-control-c-to-threads-413317.html" rel="nofollow noreferrer">Sending sig INT ( control C ) to threads - Dev Shed</a></li>
  <li><a href="http://www.perlmonks.org/?node_id=828184" rel="nofollow noreferrer">SOLVED: Is this a bug of perl threads ? - Perl Monks</a></li>
  <li><a href="http://www.perlmonks.org/?node_id=436492" rel="nofollow noreferrer">How do we capture CTRL ^ C - Perl Monks</a></li>
  <li><a href="http://www.perlmonks.org/?node_id=707861" rel="nofollow noreferrer">Is the signal handler supposed to work like this?</a></li>
  </ul>
  
  <p>... but I cannot say if it conclusively answers whether "capturing" Ctrl-C under perl in bash is definitely impossible? </p>
  
  <p>Thanks in advance for any answers,<br>
  Cheers!</p>
  
  <hr>
  
  <p>Ok, I think I got it (<em>but I'm leaving the previous entry (below) for reference ...</em>) </p>
  
  <p>The trick turns out to be that, from the main SIGINT handler, one must signal the thread via <code>kill</code> - AND then thread also needs to have a separate SIGINT handler (from the first link in OP); AND instead of just <code>join()</code>, one needs to use the code in the <a href="https://stackoverflow.com/questions/7534566/perl-trapping-ctrl-c-with-threads-in-bash/7534771#7534771">answer by @ikegami</a>:</p>
  
  <pre><code>#!/usr/bin/env perl
  
  use threads;
  use threads::shared; # for shared variables
  
  my $cnt :shared = 0;
  my $toexit :shared = 0;
  
  
  sub counter() {
    $SIG{'INT'} = sub { print "Thread exit\n"; threads-&gt;exit(); };
    my $lexit = 0;
    while (not($lexit)) {
      { lock($toexit);
      $lexit = $toexit;
      }
      $cnt++;
      print "thread: $cnt \n";
      sleep 1;
    }
    print "out\n";
  }
  
  my $mthr;
  
  sub finisher{
    { lock($toexit);
    $toexit = 1;
    }
    $mthr-&gt;kill('INT');
  };
  
  $SIG{INT} = \&amp;finisher;
  
  $mthr = threads-&gt;create(\&amp;counter);
  
  
  print "prejoin\n";
  #~ $mthr-&gt;join();
  
  while (threads-&gt;list()) {
     my @joinable = threads-&gt;list(threads::joinable);
     if (@joinable) {
        $_-&gt;join for @joinable;
     } else {
        sleep(0.050);
     }
  }
  print "postjoin\n";
  </code></pre>
  
  <p>I may be overkilling it with the <code>$toexit</code> there, but at least now this is the result:</p>
  
  <pre><code>$ ./test.pl
  prejoin
  thread: 1 
  thread: 2 
  thread: 3 
  ^CThread exit
  postjoin
  </code></pre>
  
  <p>Many thanks to all for the solution :)<br>
  Cheers!</p>
  
  <p>&nbsp;</p>
  
  <hr>
  
  <p>Thanks to the suggestion by @mob for <code>PERL_SIGNALS</code> to <code>unsafe</code> (<i>note, <a href="http://groups.google.com/group/perl.perl5.porters/browse_thread/thread/7cd25dcb2661ed67/3eeb441f1ce3e959?lnk=raot" rel="nofollow noreferrer">Perl 5.14 does not allow "internal" setting of $ENV{'PERL_SIGNALS'}</a></i>), I'm getting somewhere - now Ctrl-C is detected - but it either terminates with a segfault, or with error: </p>
  
  <pre><code>#!/usr/bin/env perl
  
  use threads;
  use threads::shared; # for shared variables
  
  my $cnt :shared = 0;
  my $toexit :shared = 0;
  
  sub counter() {
    my $lexit = 0;
    while (not($lexit)) {
      { lock($toexit);
      $lexit = $toexit;
      }
      $cnt++;
      print "thread: $cnt \n";
      sleep 1;
    }
    print "out\n";
    #~ threads-&gt;detach(); # Thread 1 terminated abnormally: Cannot detach a joined thread
    #~ exit;
  }
  
  my $mthr;
  
  # [http://code.activestate.com/lists/perl5-porters/164923/ [perl #92246] Perl 5.14 does not allow "internal" setting of $ENV ...]
  sub finisher{
    ### Thread exit! ...
    #~ print "IIII";
    # anything here results with: Perl exited with active threads:
    #~ threads-&gt;exit();
    #~ threads-&gt;join();
    #~ $mthr-&gt;exit();
    #~ $mthr-&gt;join();
    #~ $mthr-&gt;detach();
    #~ $mthr-&gt;kill();
    #~ threads-&gt;exit() if threads-&gt;can('exit');   # Thread friendly
    #~ die;
    { lock($toexit);
    $toexit = 1;
    }
    #~ threads-&gt;join(); #
  };
  
  
  
  
  # any of these will cause stop of reaction to Ctrl-C
  $SIG{INT} = \&amp;finisher;
  #~ $SIG{INT} = sub {print "EEE\n" ; die; } ;
  #~ $SIG{INT} = 'IGNORE';
  
  # setting to DEFAULT, brings usual behavior back
  #~ $SIG{INT} = 'DEFAULT';
  
  $mthr = threads-&gt;create(\&amp;counter);
  print "prejoin\n";
  $mthr-&gt;join();
  print "postjoin\n";
  </code></pre>
  
  <p>With the comments as above, that code react with: </p>
  
  <pre><code>$ PERL_SIGNALS="unsafe" ./testloop06.pl
  prejoin
  thread: 1 
  thread: 2 
  thread: 3 
  ^Cthread: 4 
  out
  Segmentation fault
  </code></pre>
  
  <p>Result is the same if I add the following that uses <a href="http://search.cpan.org/perldoc?Perl::Signals::Unsafe" rel="nofollow noreferrer">Perl::Signals::Unsafe</a>:</p>
  
  <pre><code>$mthr = threads-&gt;create(\&amp;counter);
  
  UNSAFE_SIGNALS {
    $mthr-&gt;join();
  };
  </code></pre>
  
  <p>Almost there, hopefully someone can chime in ... :) </p>