xref: /openbsd/gnu/usr.bin/perl/t/op/sigdispatch.t (revision b8851fcc)
1898184e3Ssthen#!perl -w
2898184e3Ssthen
3898184e3Ssthen# We assume that TestInit has been used.
4898184e3Ssthen
5898184e3SsthenBEGIN {
6*b8851fccSafresh1      chdir 't' if -d 't';
7898184e3Ssthen      require './test.pl';
8898184e3Ssthen}
9898184e3Ssthen
10898184e3Ssthenuse strict;
11898184e3Ssthenuse Config;
12898184e3Ssthen
1391f110e0Safresh1plan tests => 29;
1491f110e0Safresh1$| = 1;
15898184e3Ssthen
166fb12b70Safresh1watchdog(25);
17898184e3Ssthen
18898184e3Ssthen$SIG{ALRM} = sub {
19898184e3Ssthen    die "Alarm!\n";
20898184e3Ssthen};
21898184e3Ssthen
22898184e3Ssthenpass('before the first loop');
23898184e3Ssthen
24898184e3Ssthenalarm 2;
25898184e3Ssthen
26898184e3Sstheneval {
27898184e3Ssthen    1 while 1;
28898184e3Ssthen};
29898184e3Ssthen
30898184e3Ssthenis($@, "Alarm!\n", 'after the first loop');
31898184e3Ssthen
32898184e3Ssthenpass('before the second loop');
33898184e3Ssthen
34898184e3Ssthenalarm 2;
35898184e3Ssthen
36898184e3Sstheneval {
37898184e3Ssthen    while (1) {
38898184e3Ssthen    }
39898184e3Ssthen};
40898184e3Ssthen
41898184e3Ssthenis($@, "Alarm!\n", 'after the second loop');
42898184e3Ssthen
43898184e3SsthenSKIP: {
44898184e3Ssthen    skip('We can\'t test blocking without sigprocmask', 17)
45898184e3Ssthen	if is_miniperl() || !$Config{d_sigprocmask};
466fb12b70Safresh1    skip("This doesn\'t work on $^O threaded builds RT#88814", 17)
47*b8851fccSafresh1        if ($^O =~ /cygwin/ && $Config{useithreads});
48*b8851fccSafresh1    skip("This doesn\'t work on $^O version $Config{osvers} RT#88814", 17)
49*b8851fccSafresh1        if ($^O eq "openbsd" && $Config{osvers} < 5.2);
50898184e3Ssthen
51898184e3Ssthen    require POSIX;
52898184e3Ssthen    my $pending = POSIX::SigSet->new();
53898184e3Ssthen    is POSIX::sigpending($pending), '0 but true', 'sigpending';
54898184e3Ssthen    is $pending->ismember(&POSIX::SIGUSR1), 0, 'SIGUSR1 is not pending';
55898184e3Ssthen    my $new = POSIX::SigSet->new(&POSIX::SIGUSR1);
56898184e3Ssthen    POSIX::sigprocmask(&POSIX::SIG_BLOCK, $new);
57898184e3Ssthen
58898184e3Ssthen    my $gotit = 0;
59898184e3Ssthen    $SIG{USR1} = sub { $gotit++ };
60898184e3Ssthen    kill 'SIGUSR1', $$;
61898184e3Ssthen    is $gotit, 0, 'Haven\'t received third signal yet';
62898184e3Ssthen
63898184e3Ssthen    diag "2nd sigpending crashes on cygwin" if $^O eq 'cygwin';
64898184e3Ssthen    is POSIX::sigpending($pending), '0 but true', 'sigpending';
65898184e3Ssthen    is $pending->ismember(&POSIX::SIGUSR1), 1, 'SIGUSR1 is pending';
66898184e3Ssthen
67898184e3Ssthen    my $old = POSIX::SigSet->new();
68898184e3Ssthen    POSIX::sigsuspend($old);
69898184e3Ssthen    is $gotit, 1, 'Received third signal';
70898184e3Ssthen    is POSIX::sigpending($pending), '0 but true', 'sigpending';
71898184e3Ssthen    is $pending->ismember(&POSIX::SIGUSR1), 0, 'SIGUSR1 is no longer pending';
72898184e3Ssthen
73898184e3Ssthen	{
74898184e3Ssthen		kill 'SIGUSR1', $$;
75898184e3Ssthen		local $SIG{USR1} = sub { die "FAIL\n" };
76898184e3Ssthen		POSIX::sigprocmask(&POSIX::SIG_BLOCK, undef, $old);
77898184e3Ssthen		ok $old->ismember(&POSIX::SIGUSR1), 'SIGUSR1 is blocked';
78898184e3Ssthen		eval { POSIX::sigsuspend(POSIX::SigSet->new) };
79898184e3Ssthen		is $@, "FAIL\n", 'Exception is thrown, so received fourth signal';
80898184e3Ssthen		POSIX::sigprocmask(&POSIX::SIG_BLOCK, undef, $old);
81898184e3SsthenTODO:
82898184e3Ssthen	    {
83898184e3Ssthen		local $::TODO = "Needs investigation" if $^O eq 'VMS';
84898184e3Ssthen		ok $old->ismember(&POSIX::SIGUSR1), 'SIGUSR1 is still blocked';
85898184e3Ssthen	    }
86898184e3Ssthen	}
87898184e3Ssthen
88898184e3Ssthen    POSIX::sigprocmask(&POSIX::SIG_BLOCK, $new);
89898184e3Ssthen    kill 'SIGUSR1', $$;
90898184e3Ssthen    is $gotit, 1, 'Haven\'t received fifth signal yet';
91898184e3Ssthen    POSIX::sigprocmask(&POSIX::SIG_UNBLOCK, $new, $old);
92898184e3Ssthen    ok $old->ismember(&POSIX::SIGUSR1), 'SIGUSR1 was still blocked';
93898184e3Ssthen    is $gotit, 2, 'Received fifth signal';
94898184e3Ssthen
95898184e3Ssthen    # test unsafe signal handlers in combination with exceptions
96898184e3Ssthen
97898184e3Ssthen    SKIP: {
98898184e3Ssthen	# #89718: on old linux kernels, this test hangs. No-ones thought
99898184e3Ssthen	# of a reliable way to probe for this, so for now, just skip the
100898184e3Ssthen	# tests on production releases
101898184e3Ssthen	skip("some OSes hang here", 3) if (int($]*1000) & 1) == 0;
102898184e3Ssthen
1036fb12b70Safresh1  SKIP: {
1046fb12b70Safresh1	skip("Issues on Android", 3) if $^O =~ /android/;
105898184e3Ssthen	my $action = POSIX::SigAction->new(sub { $gotit--, die }, POSIX::SigSet->new, 0);
106898184e3Ssthen	POSIX::sigaction(&POSIX::SIGALRM, $action);
107898184e3Ssthen	eval {
108898184e3Ssthen	    alarm 1;
109898184e3Ssthen	    my $set = POSIX::SigSet->new;
110898184e3Ssthen	    POSIX::sigprocmask(&POSIX::SIG_BLOCK, undef, $set);
111898184e3Ssthen	    is $set->ismember(&POSIX::SIGALRM), 0, "SIGALRM is not blocked on attempt $_";
112898184e3Ssthen	    POSIX::sigsuspend($set);
113898184e3Ssthen	} for 1..2;
114898184e3Ssthen	is $gotit, 0, 'Received both signals';
115898184e3Ssthen    }
116898184e3Ssthen}
1176fb12b70Safresh1}
118898184e3Ssthen
119898184e3SsthenSKIP: {
120898184e3Ssthen    skip("alarm cannot interrupt blocking system calls on $^O", 2)
121898184e3Ssthen	if $^O =~ /MSWin32|cygwin|VMS/;
122898184e3Ssthen    # RT #88774
123898184e3Ssthen    # make sure the signal handler's called in an eval block *before*
124898184e3Ssthen    # the eval is popped
125898184e3Ssthen
126898184e3Ssthen    $SIG{'ALRM'} = sub { die "HANDLER CALLED\n" };
127898184e3Ssthen
128898184e3Ssthen    eval {
129898184e3Ssthen	alarm(2);
130898184e3Ssthen	select(undef,undef,undef,10);
131898184e3Ssthen    };
132898184e3Ssthen    alarm(0);
133898184e3Ssthen    is($@, "HANDLER CALLED\n", 'block eval');
134898184e3Ssthen
135898184e3Ssthen    eval q{
136898184e3Ssthen	alarm(2);
137898184e3Ssthen	select(undef,undef,undef,10);
138898184e3Ssthen    };
139898184e3Ssthen    alarm(0);
140898184e3Ssthen    is($@, "HANDLER CALLED\n", 'string eval');
141898184e3Ssthen}
142898184e3Ssthen
143898184e3Sstheneval { $SIG{"__WARN__\0"} = sub { 1 } };
144898184e3Ssthenlike $@, qr/No such hook: __WARN__\\0 at/, q!Fetching %SIG hooks with an extra trailing nul is nul-clean!;
145898184e3Ssthen
146898184e3Sstheneval { $SIG{"__DIE__\0whoops"} = sub { 1 } };
147898184e3Ssthenlike $@, qr/No such hook: __DIE__\\0whoops at/;
148898184e3Ssthen
149898184e3Ssthen{
150898184e3Ssthen    use warnings;
151898184e3Ssthen    my $w;
152898184e3Ssthen    local $SIG{__WARN__} = sub { $w = shift };
153898184e3Ssthen
154898184e3Ssthen    $SIG{"KILL\0"} = sub { 1 };
155898184e3Ssthen    like $w, qr/No such signal: SIGKILL\\0 at/, 'Arbitrary signal lookup through %SIG is clean';
156898184e3Ssthen}
15791f110e0Safresh1
15891f110e0Safresh1# [perl #45173]
15991f110e0Safresh1{
16091f110e0Safresh1    my $int_called;
16191f110e0Safresh1    local $SIG{INT} = sub { $int_called = 1; };
16291f110e0Safresh1    $@ = "died";
16391f110e0Safresh1    is($@, "died");
16491f110e0Safresh1    kill 'INT', $$;
16591f110e0Safresh1    # this is needed to ensure signal delivery on MSWin32
16691f110e0Safresh1    sleep(1);
16791f110e0Safresh1    is($int_called, 1);
16891f110e0Safresh1    is($@, "died");
16991f110e0Safresh1}
170