summaryrefslogtreecommitdiff
path: root/ext/POSIX/POSIX.xs
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2019-11-11 16:06:26 +0000
committerDavid Mitchell <davem@iabyn.com>2019-11-18 09:34:40 +0000
commit19c9c2ee4a859f540f01b8d5592fd27d3fbfb253 (patch)
treee280456e2d95a909487e123b98ce1eab99444ec4 /ext/POSIX/POSIX.xs
parentdc37125bb824744e1f528311ca37da59913cda7d (diff)
downloadperl-19c9c2ee4a859f540f01b8d5592fd27d3fbfb253.tar.gz
POSIX::sigaction(): use correct sig handler
Depending on whether sigaction() is called with the SA_SIGINFO flag set, it should be setting either a 1-arg or 3-arg signal handler for the kernel to call back. In fact it was always passing a 3-arg handler, and telling the kernel that it was a 1-arg handler, which means that in 1-arg handler situations, the handler was being called with args 2 and 3 containing random garbage. Instead, use the newly-added explicit-arg handler functions, which take the specified number of args regardless of OS / configuration.` There's a temporary hack included in the patch because perl core is still claiming to use 3-arg handlers while actually supplying 1-arg ones. This will be fixed shortly and the hack removed.
Diffstat (limited to 'ext/POSIX/POSIX.xs')
-rw-r--r--ext/POSIX/POSIX.xs53
1 files changed, 39 insertions, 14 deletions
diff --git a/ext/POSIX/POSIX.xs b/ext/POSIX/POSIX.xs
index 311ed73c8b..3f7a2aafcf 100644
--- a/ext/POSIX/POSIX.xs
+++ b/ext/POSIX/POSIX.xs
@@ -3053,6 +3053,8 @@ sigaction(sig, optaction, oldaction = 0)
/* Remember old disposition if desired. */
if (oldaction) {
+ int safe;
+
svp = hv_fetchs(oldaction, "HANDLER", TRUE);
if(!svp)
croak("Can't supply an oldaction without a HANDLER");
@@ -3083,24 +3085,51 @@ sigaction(sig, optaction, oldaction = 0)
svp = hv_fetchs(oldaction, "FLAGS", TRUE);
sv_setiv(*svp, oact.sa_flags);
- /* Get back whether the old handler used safe signals. */
+ /* Get back whether the old handler used safe signals;
+ * i.e. it used Perl_csighandler[13] rather than
+ * Perl_sighandler[13]
+ */
+ safe = ((oact.sa_flags & SA_SIGINFO)
+ ? ( oact.sa_sigaction == PL_csighandler3p
+#ifdef PERL_USE_3ARG_SIGHANDLER
+ || oact.sa_sigaction == PL_csighandlerp
+#endif
+ )
+ : ( oact.sa_handler == PL_csighandler1p
+ || oact.sa_handler == PL_csighandlerp /* XXX tmp */
+#ifndef PERL_USE_3ARG_SIGHANDLER
+ || oact.sa_handler == PL_csighandlerp
+#endif
+ )
+ );
+
svp = hv_fetchs(oldaction, "SAFE", TRUE);
- sv_setiv(*svp,
- /* compare incompatible pointers by casting to integer */
- PTR2nat(oact.sa_handler) == PTR2nat(PL_csighandlerp));
+ sv_setiv(*svp, safe);
}
if (action) {
+ int safe;
+
+ /* Set up any desired flags. */
+ svp = hv_fetchs(action, "FLAGS", FALSE);
+ act.sa_flags = svp ? SvIV(*svp) : 0;
+
/* Safe signals use "csighandler", which vectors through the
PL_sighandlerp pointer when it's safe to do so.
(BTW, "csighandler" is very different from "sighandler".) */
svp = hv_fetchs(action, "SAFE", FALSE);
- act.sa_handler =
- DPTR2FPTR(
- void (*)(int),
- (*svp && SvTRUE(*svp))
- ? PL_csighandlerp : PL_sighandlerp
- );
+ safe = *svp && SvTRUE(*svp);
+
+ if (act.sa_flags & SA_SIGINFO) {
+ /* 3-arg handler */
+ act.sa_sigaction =
+ safe ? PL_csighandler3p : PL_sighandler3p;
+ }
+ else {
+ /* 1-arg handler */
+ act.sa_handler =
+ safe ? PL_csighandler1p : PL_sighandler1p;
+ }
/* Vector new Perl handler through %SIG.
(The core signal handlers read %SIG to dispatch.) */
@@ -3135,10 +3164,6 @@ sigaction(sig, optaction, oldaction = 0)
else
sigemptyset(& act.sa_mask);
- /* Set up any desired flags. */
- svp = hv_fetchs(action, "FLAGS", FALSE);
- act.sa_flags = svp ? SvIV(*svp) : 0;
-
/* Don't worry about cleaning up *sigsvp if this fails,
* because that means we tried to disposition a
* nonblockable signal, in which case *sigsvp is