This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Skip over state declarations at run time
[perl5.git] / t / op / sigdispatch.t
CommitLineData
8f3964af
NC
1#!perl -w
2
3# We assume that TestInit has been used.
4
5BEGIN {
b5efbd1f 6 chdir 't' if -d 't';
8f3964af
NC
7 require './test.pl';
8}
9
10use strict;
0c1bf4c7 11use Config;
8f3964af 12
100c03aa 13plan tests => 29;
6281d426 14$| = 1;
8f3964af 15
a75b628d 16watchdog(25);
8f3964af
NC
17
18$SIG{ALRM} = sub {
19 die "Alarm!\n";
20};
21
22pass('before the first loop');
23
24alarm 2;
25
26eval {
27 1 while 1;
28};
29
30is($@, "Alarm!\n", 'after the first loop');
31
32pass('before the second loop');
33
34alarm 2;
35
36eval {
37 while (1) {
38 }
39};
40
41is($@, "Alarm!\n", 'after the second loop');
0c1bf4c7
LT
42
43SKIP: {
61fb63a6 44 skip('We can\'t test blocking without sigprocmask', 17)
b93d0e62 45 if is_miniperl() || !$Config{d_sigprocmask};
054559e9
TC
46 skip("This doesn\'t work on $^O threaded builds RT#88814", 17)
47 if ($^O =~ /cygwin/ || $^O eq "openbsd" && $Config{osvers} < 5.2)
48 && $Config{useithreads};
0c1bf4c7
LT
49
50 require POSIX;
61fb63a6
NC
51 my $pending = POSIX::SigSet->new();
52 is POSIX::sigpending($pending), '0 but true', 'sigpending';
53 is $pending->ismember(&POSIX::SIGUSR1), 0, 'SIGUSR1 is not pending';
0c1bf4c7
LT
54 my $new = POSIX::SigSet->new(&POSIX::SIGUSR1);
55 POSIX::sigprocmask(&POSIX::SIG_BLOCK, $new);
56
57 my $gotit = 0;
58 $SIG{USR1} = sub { $gotit++ };
eb796c7f 59 kill 'SIGUSR1', $$;
7fe50b8b 60 is $gotit, 0, 'Haven\'t received third signal yet';
0ac0889d
RU
61
62 diag "2nd sigpending crashes on cygwin" if $^O eq 'cygwin';
61fb63a6
NC
63 is POSIX::sigpending($pending), '0 but true', 'sigpending';
64 is $pending->ismember(&POSIX::SIGUSR1), 1, 'SIGUSR1 is pending';
0c1bf4c7
LT
65
66 my $old = POSIX::SigSet->new();
67 POSIX::sigsuspend($old);
68 is $gotit, 1, 'Received third signal';
61fb63a6
NC
69 is POSIX::sigpending($pending), '0 but true', 'sigpending';
70 is $pending->ismember(&POSIX::SIGUSR1), 0, 'SIGUSR1 is no longer pending';
0c1bf4c7 71
7fe50b8b 72 {
eb796c7f 73 kill 'SIGUSR1', $$;
7fe50b8b
LT
74 local $SIG{USR1} = sub { die "FAIL\n" };
75 POSIX::sigprocmask(&POSIX::SIG_BLOCK, undef, $old);
76 ok $old->ismember(&POSIX::SIGUSR1), 'SIGUSR1 is blocked';
77 eval { POSIX::sigsuspend(POSIX::SigSet->new) };
78 is $@, "FAIL\n", 'Exception is thrown, so received fourth signal';
79 POSIX::sigprocmask(&POSIX::SIG_BLOCK, undef, $old);
23292af3
CB
80TODO:
81 {
82 local $::TODO = "Needs investigation" if $^O eq 'VMS';
7fe50b8b 83 ok $old->ismember(&POSIX::SIGUSR1), 'SIGUSR1 is still blocked';
23292af3 84 }
7fe50b8b
LT
85 }
86
554bc0f4 87 POSIX::sigprocmask(&POSIX::SIG_BLOCK, $new);
eb796c7f 88 kill 'SIGUSR1', $$;
554bc0f4
LT
89 is $gotit, 1, 'Haven\'t received fifth signal yet';
90 POSIX::sigprocmask(&POSIX::SIG_UNBLOCK, $new, $old);
91 ok $old->ismember(&POSIX::SIGUSR1), 'SIGUSR1 was still blocked';
7fe50b8b 92 is $gotit, 2, 'Received fifth signal';
c22d665b
LT
93
94 # test unsafe signal handlers in combination with exceptions
8aed2c65
DM
95
96 SKIP: {
97 # #89718: on old linux kernels, this test hangs. No-ones thought
98 # of a reliable way to probe for this, so for now, just skip the
99 # tests on production releases
100 skip("some OSes hang here", 3) if (int($]*1000) & 1) == 0;
5322aba4 101
4f7dee4f
BF
102 SKIP: {
103 skip("Issues on Android", 3) if $^O =~ /android/;
8aed2c65
DM
104 my $action = POSIX::SigAction->new(sub { $gotit--, die }, POSIX::SigSet->new, 0);
105 POSIX::sigaction(&POSIX::SIGALRM, $action);
106 eval {
107 alarm 1;
108 my $set = POSIX::SigSet->new;
109 POSIX::sigprocmask(&POSIX::SIG_BLOCK, undef, $set);
110 is $set->ismember(&POSIX::SIGALRM), 0, "SIGALRM is not blocked on attempt $_";
111 POSIX::sigsuspend($set);
112 } for 1..2;
113 is $gotit, 0, 'Received both signals';
114 }
0c1bf4c7 115}
5322aba4 116}
011c3814 117
476c37e2
NC
118SKIP: {
119 skip("alarm cannot interrupt blocking system calls on $^O", 2)
0ac0889d 120 if $^O =~ /MSWin32|cygwin|VMS/;
011c3814
DM
121 # RT #88774
122 # make sure the signal handler's called in an eval block *before*
123 # the eval is popped
124
125 $SIG{'ALRM'} = sub { die "HANDLER CALLED\n" };
126
127 eval {
128 alarm(2);
129 select(undef,undef,undef,10);
130 };
131 alarm(0);
132 is($@, "HANDLER CALLED\n", 'block eval');
133
134 eval q{
135 alarm(2);
136 select(undef,undef,undef,10);
137 };
138 alarm(0);
139 is($@, "HANDLER CALLED\n", 'string eval');
140}
84c7b88c
BF
141
142eval { $SIG{"__WARN__\0"} = sub { 1 } };
143like $@, qr/No such hook: __WARN__\\0 at/, q!Fetching %SIG hooks with an extra trailing nul is nul-clean!;
144
145eval { $SIG{"__DIE__\0whoops"} = sub { 1 } };
146like $@, qr/No such hook: __DIE__\\0whoops at/;
147
148{
149 use warnings;
150 my $w;
151 local $SIG{__WARN__} = sub { $w = shift };
152
153 $SIG{"KILL\0"} = sub { 1 };
154 like $w, qr/No such signal: SIGKILL\\0 at/, 'Arbitrary signal lookup through %SIG is clean';
155}
100c03aa
JL
156
157# [perl #45173]
158{
6281d426
TC
159 my $int_called;
160 local $SIG{INT} = sub { $int_called = 1; };
100c03aa
JL
161 $@ = "died";
162 is($@, "died");
6281d426
TC
163 kill 'INT', $$;
164 # this is needed to ensure signal delivery on MSWin32
165 sleep(1);
166 is($int_called, 1);
100c03aa
JL
167 is($@, "died");
168}