The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
package main;
use Signals::XSIG;
use t::SignalHandlerTest;
use Test::More tests => 19;
use Config;
use strict;
use warnings;
no warnings 'signal';

# does our %XSIG signal handling framework still work after we
# local'ize an element of %XSIG or %SIG? If we local'ize all
# of %XSIG or %SIG?

sub foo { 42 }
sub bar { 43 }

my $s = appropriate_signals();

ok(!defined($SIG{$s}));
$SIG{$s} = 'main::foo';
ok($SIG{$s} eq 'main::foo');
ok($XSIG{$s}[0] eq 'main::foo');
my $oldreg = $XSIG{$s}[0];

my %z = %SIG;
{
  local $SIG{$s} = 'DEFAULT';
  ok($SIG{$s} eq 'DEFAULT');
  ok(tied %SIG);
  ok($XSIG{$s}[0] eq 'DEFAULT');
}

ok(tied %SIG, "tied hash restored after local \$SIG{...}");
ok($SIG{$s} eq 'main::foo', "hash val restored after local \$SIG{...}");
ok($XSIG{$s}[0] eq $oldreg, "XSIG val restored");

my $restored = 1;
for my $k (keys %z) {
  next unless defined($z{$k}) || defined($SIG{$k});
  $restored &&= $z{$k} eq $SIG{$k};
}
ok($restored, "hash val restored after local \$SIG{...}");


#
#     { local %SIG; ... }
#
# will break the tied functionality, so don't do that and avoid
# modules that do that:
#
#     PAR::Dist::_unzip
#
#     { local $SIG{signal} = ... }  is ok, though.
#
# only workaround is to save and restore the whole table
# when the local var goes out of scope.

{
  ok(tied %SIG, "\%SIG tied before localization");

  %z = %SIG;
  SKIP: {
    local %SIG;
    $SIG{$s} = 'IGNORE';
    ok($SIG{$s} eq 'IGNORE', 'set $SIG{sig}');

    # failure point with perl 5.13 and 5.14
    if ($Config{PERL_VERSION} >= 13) {
      skip 'local breaks tie since 5.13', 2;
    }
    ok(tied %SIG, "\%SIG tied during localization");   ### 13 ###
    ok($XSIG{$s}[0] eq 'IGNORE', 'set $XSIG{sig}');    ### 14 ###
  }

  # perl 5.6,5.8 - lots of uninitialized warnings here
  no warnings 'uninitialized';
  %SIG = %z;
  ok(tied %SIG, "\%SIG tied after localization");
}

ok(tied %SIG, "tied hash restored after local \%SIG");
ok($SIG{$s} eq 'main::foo', "hash val restored after local \%SIG");
ok($XSIG{$s}[0] eq $oldreg, "XSIG val restored");
$restored = 1;
for my $k (keys %z) {
  no warnings 'uninitialized';
  next unless defined($z{$k}) || defined($SIG{$k});
  $restored &&= $z{$k} eq $SIG{$k};
}
ok($restored, "hash val restored after local \%SIG");


__END__

# do extended signal handlers run when %SIG is local?
#  

$s = 'ALRM';
%z = %SIG;
ok(tied %SIG);
my ($x,$y,$z) = (0,0,0);
$XSIG{$s} = [ sub { $x=1 }, sub { $y=$z=1 } ];
trigger($s);
ok($x==1 && $y==1 && $z==1);
$x=$y=$z=0;
{
  local %SIG;
  $SIG{$s} = sub { $x=2 };
  trigger($s);
  ok($x==2);

  # this works on 5.8, fails on >= 5.10
  ok($y==1 && $z==1, '%XSIG handlers run after local %SIG');
}