summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mg.c16
-rw-r--r--t/op/sigdispatch.t8
2 files changed, 21 insertions, 3 deletions
diff --git a/mg.c b/mg.c
index c58531e6fc..5b6b339733 100644
--- a/mg.c
+++ b/mg.c
@@ -3106,15 +3106,27 @@ Perl_sighandler(int sig)
POPSTACK;
if (SvTRUE(ERRSV)) {
-#if !defined(PERL_MICRO) && !defined(HAS_SIGPROCMASK)
+#ifndef PERL_MICRO
/* Handler "died", for example to get out of a restart-able read().
* Before we re-do that on its behalf re-enable the signal which was
* blocked by the system when we entered.
*/
+#ifdef HAS_SIGPROCMASK
+#ifdef HAS_SIGACTION
+ if (sip)
+#endif
+ {
+ sigset_t set;
+ sigemptyset(&set);
+ sigaddset(&set,sig);
+ sigprocmask(SIG_UNBLOCK, &set, NULL);
+ }
+#else
/* Not clear if this will work */
(void)rsignal(sig, SIG_IGN);
(void)rsignal(sig, PL_csighandlerp);
-#endif /* !PERL_MICRO && !HAS_SIGPROCMASK*/
+#endif
+#endif /* !PERL_MICRO */
die_sv(ERRSV);
}
cleanup:
diff --git a/t/op/sigdispatch.t b/t/op/sigdispatch.t
index e3c8fdb110..5a5fc14671 100644
--- a/t/op/sigdispatch.t
+++ b/t/op/sigdispatch.t
@@ -9,7 +9,7 @@ BEGIN {
use strict;
use Config;
-plan tests => 12;
+plan tests => 13;
watchdog(10);
@@ -70,4 +70,10 @@ SKIP: {
POSIX::sigprocmask(&POSIX::SIG_UNBLOCK, $new, $old);
ok $old->ismember(&POSIX::SIGUSR1), 'SIGUSR1 was still blocked';
is $gotit, 2, 'Received fifth signal';
+
+ # test unsafe signal handlers in combination with exceptions
+ my $action = POSIX::SigAction->new(sub { $gotit--, die }, POSIX::SigSet->new, 0);
+ POSIX::sigaction(&POSIX::SIGUSR1, $action);
+ eval { kill SIGUSR1, $$ } for 1..2;
+ is $gotit, 0, 'Received both signals';
}