1*0Sstevel@tonic-gate#!./perl 2*0Sstevel@tonic-gate 3*0Sstevel@tonic-gateBEGIN { 4*0Sstevel@tonic-gate chdir 't' if -d 't'; 5*0Sstevel@tonic-gate unshift @INC, '../lib'; 6*0Sstevel@tonic-gate} 7*0Sstevel@tonic-gate 8*0Sstevel@tonic-gateBEGIN{ 9*0Sstevel@tonic-gate # Don't do anything if POSIX is missing, or sigaction missing. 10*0Sstevel@tonic-gate use Config; 11*0Sstevel@tonic-gate eval 'use POSIX'; 12*0Sstevel@tonic-gate if($@ || $^O eq 'MSWin32' || $^O eq 'NetWare' || $^O eq 'dos' || 13*0Sstevel@tonic-gate $^O eq 'MacOS' || ($^O eq 'VMS' && !$Config{'d_sigaction'})) { 14*0Sstevel@tonic-gate print "1..0\n"; 15*0Sstevel@tonic-gate exit 0; 16*0Sstevel@tonic-gate } 17*0Sstevel@tonic-gate} 18*0Sstevel@tonic-gate 19*0Sstevel@tonic-gateuse strict; 20*0Sstevel@tonic-gateuse vars qw/$bad7 $ok10 $bad18 $ok/; 21*0Sstevel@tonic-gate 22*0Sstevel@tonic-gate$^W=1; 23*0Sstevel@tonic-gate 24*0Sstevel@tonic-gateprint "1..25\n"; 25*0Sstevel@tonic-gate 26*0Sstevel@tonic-gatesub IGNORE { 27*0Sstevel@tonic-gate $bad7=1; 28*0Sstevel@tonic-gate} 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gatesub DEFAULT { 31*0Sstevel@tonic-gate $bad18=1; 32*0Sstevel@tonic-gate} 33*0Sstevel@tonic-gate 34*0Sstevel@tonic-gatesub foo { 35*0Sstevel@tonic-gate $ok=1; 36*0Sstevel@tonic-gate} 37*0Sstevel@tonic-gate 38*0Sstevel@tonic-gatemy $newaction=POSIX::SigAction->new('::foo', new POSIX::SigSet(SIGUSR1), 0); 39*0Sstevel@tonic-gatemy $oldaction=POSIX::SigAction->new('::bar', new POSIX::SigSet(), 0); 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gate{ 42*0Sstevel@tonic-gate my $bad; 43*0Sstevel@tonic-gate local($SIG{__WARN__})=sub { $bad=1; }; 44*0Sstevel@tonic-gate sigaction(SIGHUP, $newaction, $oldaction); 45*0Sstevel@tonic-gate if($bad) { print "not ok 1\n" } else { print "ok 1\n"} 46*0Sstevel@tonic-gate} 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gateif($oldaction->{HANDLER} eq 'DEFAULT' || 49*0Sstevel@tonic-gate $oldaction->{HANDLER} eq 'IGNORE') 50*0Sstevel@tonic-gate { print "ok 2\n" } else { print "not ok 2 # ", $oldaction->{HANDLER}, "\n"} 51*0Sstevel@tonic-gateprint $SIG{HUP} eq '::foo' ? "ok 3\n" : "not ok 3\n"; 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gatesigaction(SIGHUP, $newaction, $oldaction); 54*0Sstevel@tonic-gateif($oldaction->{HANDLER} eq '::foo') 55*0Sstevel@tonic-gate { print "ok 4\n" } else { print "not ok 4\n"} 56*0Sstevel@tonic-gateif($oldaction->{MASK}->ismember(SIGUSR1)) 57*0Sstevel@tonic-gate { print "ok 5\n" } else { print "not ok 5\n"} 58*0Sstevel@tonic-gateif($oldaction->{FLAGS}) { 59*0Sstevel@tonic-gate if ($^O eq 'linux' || $^O eq 'unicos') { 60*0Sstevel@tonic-gate print "ok 6 # Skip: sigaction() thinks different in $^O\n"; 61*0Sstevel@tonic-gate } else { 62*0Sstevel@tonic-gate print "not ok 6\n"; 63*0Sstevel@tonic-gate } 64*0Sstevel@tonic-gate} else { 65*0Sstevel@tonic-gate print "ok 6\n"; 66*0Sstevel@tonic-gate} 67*0Sstevel@tonic-gate 68*0Sstevel@tonic-gate$newaction=POSIX::SigAction->new('IGNORE'); 69*0Sstevel@tonic-gatesigaction(SIGHUP, $newaction); 70*0Sstevel@tonic-gatekill 'HUP', $$; 71*0Sstevel@tonic-gateprint $bad7 ? "not ok 7\n" : "ok 7\n"; 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gateprint $SIG{HUP} eq 'IGNORE' ? "ok 8\n" : "not ok 8\n"; 74*0Sstevel@tonic-gatesigaction(SIGHUP, POSIX::SigAction->new('DEFAULT')); 75*0Sstevel@tonic-gateprint $SIG{HUP} eq 'DEFAULT' ? "ok 9\n" : "not ok 9\n"; 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate$newaction=POSIX::SigAction->new(sub { $ok10=1; }); 78*0Sstevel@tonic-gatesigaction(SIGHUP, $newaction); 79*0Sstevel@tonic-gate{ 80*0Sstevel@tonic-gate local($^W)=0; 81*0Sstevel@tonic-gate kill 'HUP', $$; 82*0Sstevel@tonic-gate} 83*0Sstevel@tonic-gateprint $ok10 ? "ok 10\n" : "not ok 10\n"; 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gateprint ref($SIG{HUP}) eq 'CODE' ? "ok 11\n" : "not ok 11\n"; 86*0Sstevel@tonic-gate 87*0Sstevel@tonic-gatesigaction(SIGHUP, POSIX::SigAction->new('::foo')); 88*0Sstevel@tonic-gate# Make sure the signal mask gets restored after sigaction croak()s. 89*0Sstevel@tonic-gateeval { 90*0Sstevel@tonic-gate my $act=POSIX::SigAction->new('::foo'); 91*0Sstevel@tonic-gate delete $act->{HANDLER}; 92*0Sstevel@tonic-gate sigaction(SIGINT, $act); 93*0Sstevel@tonic-gate}; 94*0Sstevel@tonic-gatekill 'HUP', $$; 95*0Sstevel@tonic-gateprint $ok ? "ok 12\n" : "not ok 12\n"; 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gateundef $ok; 98*0Sstevel@tonic-gate# Make sure the signal mask gets restored after sigaction returns early. 99*0Sstevel@tonic-gatemy $x=defined sigaction(SIGKILL, $newaction, $oldaction); 100*0Sstevel@tonic-gatekill 'HUP', $$; 101*0Sstevel@tonic-gateprint !$x && $ok ? "ok 13\n" : "not ok 13\n"; 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate$SIG{HUP}=sub {}; 104*0Sstevel@tonic-gatesigaction(SIGHUP, $newaction, $oldaction); 105*0Sstevel@tonic-gateprint ref($oldaction->{HANDLER}) eq 'CODE' ? "ok 14\n" : "not ok 14\n"; 106*0Sstevel@tonic-gate 107*0Sstevel@tonic-gateeval { 108*0Sstevel@tonic-gate sigaction(SIGHUP, undef, $oldaction); 109*0Sstevel@tonic-gate}; 110*0Sstevel@tonic-gateprint $@ ? "not ok 15\n" : "ok 15\n"; 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gateeval { 113*0Sstevel@tonic-gate sigaction(SIGHUP, 0, $oldaction); 114*0Sstevel@tonic-gate}; 115*0Sstevel@tonic-gateprint $@ ? "not ok 16\n" : "ok 16\n"; 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gateeval { 118*0Sstevel@tonic-gate sigaction(SIGHUP, bless({},'Class'), $oldaction); 119*0Sstevel@tonic-gate}; 120*0Sstevel@tonic-gateprint $@ ? "ok 17\n" : "not ok 17\n"; 121*0Sstevel@tonic-gate 122*0Sstevel@tonic-gateif ($^O eq 'VMS') { 123*0Sstevel@tonic-gate print "ok 18 # Skip: SIGCONT not trappable in $^O\n"; 124*0Sstevel@tonic-gate} else { 125*0Sstevel@tonic-gate $newaction=POSIX::SigAction->new(sub { $ok10=1; }); 126*0Sstevel@tonic-gate if (eval { SIGCONT; 1 }) { 127*0Sstevel@tonic-gate sigaction(SIGCONT, POSIX::SigAction->new('DEFAULT')); 128*0Sstevel@tonic-gate { 129*0Sstevel@tonic-gate local($^W)=0; 130*0Sstevel@tonic-gate kill 'CONT', $$; 131*0Sstevel@tonic-gate } 132*0Sstevel@tonic-gate } 133*0Sstevel@tonic-gate print $bad18 ? "not ok 18\n" : "ok 18\n"; 134*0Sstevel@tonic-gate} 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gate{ 137*0Sstevel@tonic-gate local $SIG{__WARN__} = sub { }; # Just suffer silently. 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gate my $hup20; 140*0Sstevel@tonic-gate my $hup21; 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate sub hup20 { $hup20++ } 143*0Sstevel@tonic-gate sub hup21 { $hup21++ } 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate sigaction("FOOBAR", $newaction); 146*0Sstevel@tonic-gate print "ok 19\n"; # no coredump, still alive 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate $newaction = POSIX::SigAction->new("hup20"); 149*0Sstevel@tonic-gate sigaction("SIGHUP", $newaction); 150*0Sstevel@tonic-gate kill "HUP", $$; 151*0Sstevel@tonic-gate print $hup20 == 1 ? "ok 20\n" : "not ok 20\n"; 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gate $newaction = POSIX::SigAction->new("hup21"); 154*0Sstevel@tonic-gate sigaction("HUP", $newaction); 155*0Sstevel@tonic-gate kill "HUP", $$; 156*0Sstevel@tonic-gate print $hup21 == 1 ? "ok 21\n" : "not ok 21\n"; 157*0Sstevel@tonic-gate} 158*0Sstevel@tonic-gate 159*0Sstevel@tonic-gate# "safe" attribute. 160*0Sstevel@tonic-gate# for this one, use the accessor instead of the attribute 161*0Sstevel@tonic-gate 162*0Sstevel@tonic-gate# standard signal handling via %SIG is safe 163*0Sstevel@tonic-gate$SIG{HUP} = \&foo; 164*0Sstevel@tonic-gate$oldaction = POSIX::SigAction->new; 165*0Sstevel@tonic-gatesigaction(SIGHUP, undef, $oldaction); 166*0Sstevel@tonic-gateprint $oldaction->safe ? "ok 22\n" : "not ok 22\n"; 167*0Sstevel@tonic-gate 168*0Sstevel@tonic-gate# SigAction handling is not safe ... 169*0Sstevel@tonic-gatesigaction(SIGHUP, POSIX::SigAction->new(\&foo)); 170*0Sstevel@tonic-gatesigaction(SIGHUP, undef, $oldaction); 171*0Sstevel@tonic-gateprint $oldaction->safe ? "not ok 23\n" : "ok 23\n"; 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate# ... unless we say so! 174*0Sstevel@tonic-gate$newaction = POSIX::SigAction->new(\&foo); 175*0Sstevel@tonic-gate$newaction->safe(1); 176*0Sstevel@tonic-gatesigaction(SIGHUP, $newaction); 177*0Sstevel@tonic-gatesigaction(SIGHUP, undef, $oldaction); 178*0Sstevel@tonic-gateprint $oldaction->safe ? "ok 24\n" : "not ok 24\n"; 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate# And safe signal delivery must work 181*0Sstevel@tonic-gate$ok = 0; 182*0Sstevel@tonic-gatekill 'HUP', $$; 183*0Sstevel@tonic-gateprint $ok ? "ok 25\n" : "not ok 25\n"; 184