This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Probe for and expose more fields for SA_SIGINFO
authorDagfinn Ilmari Mannsåker <ilmari@ilmari.org>
Tue, 12 Jan 2016 14:47:07 +0000 (14:47 +0000)
committerDagfinn Ilmari Mannsåker <ilmari@ilmari.org>
Tue, 26 Jan 2016 10:51:42 +0000 (10:51 +0000)
These are all specified by POSIX/SUSv3, but not all platforms have them,
as mentioned in POSIX.pm.

We can only test the pid, uid and code fields, since they are the only
ones that are defined for a user-sent signal.

17 files changed:
Configure
Cross/config.sh-arm-linux
NetWare/config.wc
Porting/config.sh
config_h.SH
configure.com
ext/POSIX/t/sigaction.t
mg.c
plan9/config_sh.sample
pod/perldelta.pod
symbian/config.sh
uconfig.h
uconfig.sh
uconfig64.sh
win32/config.ce
win32/config.gc
win32/config.vc

index d5a7de3..3d65fd2 100755 (executable)
--- a/Configure
+++ b/Configure
@@ -785,6 +785,13 @@ d_shmctl=''
 d_shmdt=''
 d_shmget=''
 d_sigaction=''
+d_siginfo_si_errno=''
+d_siginfo_si_pid=''
+d_siginfo_si_uid=''
+d_siginfo_si_addr=''
+d_siginfo_si_status=''
+d_siginfo_si_band=''
+d_siginfo_si_value=''
 d_signbit=''
 d_sigprocmask=''
 d_sigsetjmp=''
@@ -10758,6 +10765,25 @@ set $varname;
 eval $setvar;
 $rm_try'
 
+: Define hasfield_t macro for Configure internal use
+hasfield_t='varname=$1; struct=$2; type=$3; field=$4; shift; shift; shift; shift;
+while $test $# -ge 2; do
+       case "$1" in
+       $define) echo "#include <$2>";;
+       esac ;
+    shift 2;
+done > try.c;
+echo "int main () { $struct foo; $type bar = foo.$field; }" >> try.c;
+set try;
+if eval $compile; then
+       val="$define";
+else
+       val="$undef";
+fi;
+set $varname;
+eval $setvar;
+$rm_try'
+
 : see if we should include time.h, sys/time.h, or both
 echo " "
 if test "X$timeincl" = X; then
@@ -22697,6 +22723,40 @@ case "$uidsign" in
        ;;
 esac
 
+: see what siginfo fields we have
+case "$d_sigaction" in
+"$define")
+       echo "Checking if your siginfo_t has si_errno field...">&4
+       set d_siginfo_si_errno siginfo_t int si_errno $d_sigaction signal.h
+       eval $hasfield_t;
+
+       echo "Checking if your siginfo_t has si_pid field...">&4
+       set d_siginfo_si_pid siginfo_t $pidtype si_pid $d_sigaction signal.h
+       eval $hasfield_t;
+
+       echo "Checking if your siginfo_t has si_uid field...">&4
+       set d_siginfo_si_uid siginfo_t $uidtype si_uid $d_sigaction signal.h
+       eval $hasfield_t;
+
+       echo "Checking if your siginfo_t has si_addr field...">&4
+       set d_siginfo_si_addr siginfo_t "void *" si_addr $d_sigaction signal.h
+       eval $hasfield_t;
+
+       echo "Checking if your siginfo_t has si_status field...">&4
+       set d_siginfo_si_status siginfo_t int si_status $d_sigaction signal.h
+       eval $hasfield_t;
+
+       echo "Checking if your siginfo_t has si_band field...">&4
+       set d_siginfo_si_band siginfo_t long si_band $d_sigaction signal.h
+       eval $hasfield_t;
+
+       echo "Checking if your siginfo_t has si_value field...">&4
+       set d_siginfo_si_value siginfo_t "union sigval" si_value $d_sigaction signal.h
+       eval $hasfield_t;
+
+       ;;
+esac
+
 : Determine if we can use sysctl with KERN_PROC_PATHNAME to find executing program
 echo " "
 echo "Determining whether we can use sysctl with KERN_PROC_PATHNAME to find executing program..." >&4
@@ -24523,6 +24583,13 @@ d_shmctl='$d_shmctl'
 d_shmdt='$d_shmdt'
 d_shmget='$d_shmget'
 d_sigaction='$d_sigaction'
+d_siginfo_si_errno='$d_siginfo_si_errno'
+d_siginfo_si_pid='$d_siginfo_si_pid'
+d_siginfo_si_uid='$d_siginfo_si_uid'
+d_siginfo_si_addr='$d_siginfo_si_addr'
+d_siginfo_si_status='$d_siginfo_si_status'
+d_siginfo_si_band='$d_siginfo_si_band'
+d_siginfo_si_value='$d_siginfo_si_value'
 d_signbit='$d_signbit'
 d_sigprocmask='$d_sigprocmask'
 d_sigsetjmp='$d_sigsetjmp'
index ea455bd..776d705 100644 (file)
@@ -500,6 +500,13 @@ d_shmctl='define'
 d_shmdt='define'
 d_shmget='define'
 d_sigaction='define'
+d_siginfo_si_addr='undef'
+d_siginfo_si_band='undef'
+d_siginfo_si_errno='undef'
+d_siginfo_si_pid='undef'
+d_siginfo_si_status='undef'
+d_siginfo_si_uid='undef'
+d_siginfo_si_value='undef'
 d_signbit='define'
 d_sigprocmask='define'
 d_sigsetjmp='define'
index d414e98..cc34a80 100644 (file)
@@ -490,6 +490,13 @@ d_shmctl='undef'
 d_shmdt='undef'
 d_shmget='undef'
 d_sigaction='undef'
+d_siginfo_si_addr='undef'
+d_siginfo_si_band='undef'
+d_siginfo_si_errno='undef'
+d_siginfo_si_pid='undef'
+d_siginfo_si_status='undef'
+d_siginfo_si_uid='undef'
+d_siginfo_si_value='undef'
 d_signbit='undef'
 d_sigprocmask='undef'
 d_sigsetjmp='undef'
index bd7ae1d..a8638b7 100644 (file)
@@ -511,6 +511,13 @@ d_shmctl='define'
 d_shmdt='define'
 d_shmget='define'
 d_sigaction='define'
+d_siginfo_si_addr='undef'
+d_siginfo_si_band='undef'
+d_siginfo_si_errno='undef'
+d_siginfo_si_pid='undef'
+d_siginfo_si_status='undef'
+d_siginfo_si_uid='undef'
+d_siginfo_si_value='undef'
 d_signbit='define'
 d_sigprocmask='define'
 d_sigsetjmp='define'
index e083524..9dd2c09 100755 (executable)
@@ -2327,6 +2327,48 @@ sed <<!GROK!THIS! >$CONFIG_H -e 's!^#undef\(.*/\)\*!/\*#define\1 \*!' -e 's!^#un
  */
 #$d_sigaction HAS_SIGACTION    /**/
 
+/* HAS_SIGINFO_SI_ERRNO:
+ *     This symbol, if defined, indicates that siginfo_t has the
+ *     si_errno member
+ */
+#$d_siginfo_si_errno HAS_SIGINFO_SI_ERRNO      /**/
+
+/* HAS_SIGINFO_SI_PID:
+ *     This symbol, if defined, indicates that siginfo_t has the
+ *     si_pid member
+ */
+#$d_siginfo_si_pid HAS_SIGINFO_SI_PID  /**/
+
+/* HAS_SIGINFO_SI_UID:
+ *     This symbol, if defined, indicates that siginfo_t has the
+ *     si_uid member
+ */
+#$d_siginfo_si_uid HAS_SIGINFO_SI_UID  /**/
+
+/* HAS_SIGINFO_SI_ADDR:
+ *     This symbol, if defined, indicates that siginfo_t has the
+ *     si_addr member
+ */
+#$d_siginfo_si_addr HAS_SIGINFO_SI_ADDR        /**/
+
+/* HAS_SIGINFO_SI_STATUS:
+ *     This symbol, if defined, indicates that siginfo_t has the
+ *     si_status member
+ */
+#$d_siginfo_si_status HAS_SIGINFO_SI_STATUS    /**/
+
+/* HAS_SIGINFO_SI_BAND:
+ *     This symbol, if defined, indicates that siginfo_t has the
+ *     si_band member
+ */
+#$d_siginfo_si_band HAS_SIGINFO_SI_BAND        /**/
+
+/* HAS_SIGINFO_SI_VALUE:
+ *     This symbol, if defined, indicates that siginfo_t has the
+ *     si_value member
+ */
+#$d_siginfo_si_value HAS_SIGINFO_SI_VALUE      /**/
+
 /* HAS_SIGSETJMP:
  *     This variable indicates to the C program that the sigsetjmp()
  *     routine is available to save the calling process's registers
index 2d674c5..c138a6d 100644 (file)
@@ -5340,6 +5340,13 @@ $ d_clearenv="undef"
 $ d_usleep="define"
 $ d_setitimer="define"
 $ d_sigaction="define"
+$ d_siginfo_si_addr="undef"
+$ d_siginfo_si_band="undef"
+$ d_siginfo_si_errno="undef"
+$ d_siginfo_si_pid="undef"
+$ d_siginfo_si_status="undef"
+$ d_siginfo_si_uid="undef"
+$ d_siginfo_si_value="undef"
 $ d_sigprocmask="define"
 $ d_truncate="define"
 $ d_wait4="define"
@@ -6294,6 +6301,13 @@ $ WC "d_shmctl='" + d_shmctl + "'"
 $ WC "d_shmdt='" + d_shmdt + "'"
 $ WC "d_shmget='" + d_shmget + "'"
 $ WC "d_sigaction='" + d_sigaction + "'"
+$ WC "d_siginfo_si_addr='" + d_siginfo_si_addr + "'"
+$ WC "d_siginfo_si_band='" + d_siginfo_si_band + "'"
+$ WC "d_siginfo_si_errno='" + d_siginfo_si_errno + "'"
+$ WC "d_siginfo_si_pid='" + d_siginfo_si_pid + "'"
+$ WC "d_siginfo_si_status='" + d_siginfo_si_status + "'"
+$ WC "d_siginfo_si_uid='" + d_siginfo_si_uid + "'"
+$ WC "d_siginfo_si_value='" + d_siginfo_si_value + "'"
 $ WC "d_signbit='" + d_signbit + "'"
 $ WC "d_sigprocmask='" + d_sigprocmask + "'"
 $ WC "d_sigsetjmp='" + d_sigsetjmp + "'"
index a0ad384..b282185 100644 (file)
@@ -11,7 +11,7 @@ BEGIN{
        }
 }
 
-use Test::More tests => 33;
+use Test::More tests => 36;
 
 use strict;
 use vars qw/$bad $bad7 $ok10 $bad18 $ok/;
@@ -191,12 +191,33 @@ SKIP: {
 }
 
 SKIP: {
+    my %siginfo = (
+        signo => SIGHUP,
+        pid => $$,
+        uid => $<,
+    );
+    my %opt_val = ( code => 'SI_USER' );
+    my %always = map +($_ => 1), qw(signo code);
+    my %skip = ( code => { darwin => "not set to SI_USER for kill()" } );
+    my $tests = keys %{{ %siginfo, %opt_val }};
     eval 'use POSIX qw(SA_SIGINFO); SA_SIGINFO';
-    skip("no SA_SIGINFO", 1) if $@;
-    skip("SA_SIGINFO is broken on AIX 4.2", 1) if ($^O.$Config{osvers}) =~ m/^aix4\.2/;
-    skip("SA_SIGINFO is broken on os390", 1) if ($^O.$Config{osvers}) =~ m/os390/;
+    skip("no SA_SIGINFO", $tests) if $@;
+    skip("SA_SIGINFO is broken on AIX 4.2", $tests) if ($^O.$Config{osvers}) =~ m/^aix4\.2/;
+    skip("SA_SIGINFO is broken on os390", $tests) if ($^O.$Config{osvers}) =~ m/os390/;
+    eval "use POSIX qw($opt_val{$_}); \$siginfo{$_} = $opt_val{$_}"
+        for keys %opt_val;
     sub hiphup {
-       is($_[1]->{signo}, SIGHUP, "SA_SIGINFO got right signal");
+        for my $field (sort keys %{{ %siginfo, %opt_val }}) {
+            SKIP: {
+                skip("siginfo_t has no $field field", 1)
+                    unless %always{$field} or ($Config{"d_siginfo_si_$field"} || '') eq 'define';
+                skip("no constant defined for SA_SIGINFO $field value $opt_val{$field}", 1)
+                    unless defined $siginfo{$field};
+                skip("SA_SIGINFO $field value is wrong on $^O: $skip{$field}{$^O}", 1)
+                    if $skip{$field}{$^O};
+                is($_[1]->{$field}, $siginfo{$field}, "SA_SIGINFO got right $field")
+            }
+        }
     }
     my $act = POSIX::SigAction->new('hiphup', 0, SA_SIGINFO);
     sigaction(SIGHUP, $act);
diff --git a/mg.c b/mg.c
index f8d8f33..bb5cba1 100644 (file)
--- a/mg.c
+++ b/mg.c
@@ -3340,13 +3340,27 @@ Perl_sighandler(int sig)
                    * addr, status, and band are defined by POSIX/SUSv3. */
                   (void)hv_stores(sih, "signo", newSViv(sip->si_signo));
                   (void)hv_stores(sih, "code", newSViv(sip->si_code));
-#if 0 /* XXX TODO: Configure scan for the existence of these, but even that does not help if the SA_SIGINFO is not implemented according to the spec. */
-                  hv_stores(sih, "errno",      newSViv(sip->si_errno));
-                  hv_stores(sih, "status",     newSViv(sip->si_status));
-                  hv_stores(sih, "uid",        newSViv(sip->si_uid));
-                  hv_stores(sih, "pid",        newSViv(sip->si_pid));
-                  hv_stores(sih, "addr",       newSVuv(PTR2UV(sip->si_addr)));
-                  hv_stores(sih, "band",       newSViv(sip->si_band));
+#ifdef HAS_SIGINFO_SI_ERRNO
+                  (void)hv_stores(sih, "errno",      newSViv(sip->si_errno));
+#endif
+#ifdef HAS_SIGINFO_SI_STATUS
+                  (void)hv_stores(sih, "status",     newSViv(sip->si_status));
+#endif
+#ifdef HAS_SIGINFO_SI_UID
+                  {
+                       SV *uid = newSV(0);
+                       sv_setuid(uid, sip->si_uid);
+                       (void)hv_stores(sih, "uid", uid);
+                  }
+#endif
+#ifdef HAS_SIGINFO_SI_PID
+                  (void)hv_stores(sih, "pid",        newSViv(sip->si_pid));
+#endif
+#ifdef HAS_SIGINFO_SI_ADDR
+                  (void)hv_stores(sih, "addr",       newSVuv(PTR2UV(sip->si_addr)));
+#endif
+#ifdef HAS_SIGINFO_SI_BAND
+                  (void)hv_stores(sih, "band",       newSViv(sip->si_band));
 #endif
                   EXTEND(SP, 2);
                   PUSHs(rv);
index 6622293..e214d89 100644 (file)
@@ -500,6 +500,13 @@ d_shmctl='undef'
 d_shmdt='undef'
 d_shmget='undef'
 d_sigaction='define'
+d_siginfo_si_addr='undef'
+d_siginfo_si_band='undef'
+d_siginfo_si_errno='undef'
+d_siginfo_si_pid='undef'
+d_siginfo_si_status='undef'
+d_siginfo_si_uid='undef'
+d_siginfo_si_value='undef'
 d_signbit='define'
 d_sigprocmask='define'
 d_sigsetjmp='define'
index 4d09b82..cacd83e 100644 (file)
@@ -27,6 +27,13 @@ here, but most should go in the L</Performance Enhancements> section.
 
 [ List each enhancement as a =head2 entry ]
 
+=head2 More fields provided to C<sigaction> callback with C<SA_SIGINFO>
+
+When passing the C<SA_SIGINFO> flag to L<sigaction|POSIX/sigaction>, the
+C<errno>, C<status>, C<uid>, C<pid>, C<addr> and C<band> fields are now
+included in the hash passed to the handler, if supported by the
+platform.
+
 =head1 Security
 
 XXX Any security-related notices go here.  In particular, any security
index c6466c9..64935b9 100644 (file)
@@ -446,6 +446,13 @@ d_shmctl='undef'
 d_shmdt='undef'
 d_shmget='undef'
 d_sigaction='undef'
+d_siginfo_si_addr='undef'
+d_siginfo_si_band='undef'
+d_siginfo_si_errno='undef'
+d_siginfo_si_pid='undef'
+d_siginfo_si_status='undef'
+d_siginfo_si_uid='undef'
+d_siginfo_si_value='undef'
 d_signbit='undef'
 d_sigprocmask='undef'
 d_sigsetjmp='undef'
index 079c73f..c7bb73f 100644 (file)
--- a/uconfig.h
+++ b/uconfig.h
  */
 /*#define HAS_SIGACTION        / **/
 
+/* HAS_SIGINFO_SI_ERRNO:
+ *     This symbol, if defined, indicates that siginfo_t has the
+ *     si_errno member
+ */
+/*#define HAS_SIGINFO_SI_ERRNO / **/
+
+/* HAS_SIGINFO_SI_PID:
+ *     This symbol, if defined, indicates that siginfo_t has the
+ *     si_pid member
+ */
+/*#define HAS_SIGINFO_SI_PID   / **/
+
+/* HAS_SIGINFO_SI_UID:
+ *     This symbol, if defined, indicates that siginfo_t has the
+ *     si_uid member
+ */
+/*#define HAS_SIGINFO_SI_UID   / **/
+
+/* HAS_SIGINFO_SI_ADDR:
+ *     This symbol, if defined, indicates that siginfo_t has the
+ *     si_addr member
+ */
+/*#define HAS_SIGINFO_SI_ADDR  / **/
+
+/* HAS_SIGINFO_SI_STATUS:
+ *     This symbol, if defined, indicates that siginfo_t has the
+ *     si_status member
+ */
+/*#define HAS_SIGINFO_SI_STATUS        / **/
+
+/* HAS_SIGINFO_SI_BAND:
+ *     This symbol, if defined, indicates that siginfo_t has the
+ *     si_band member
+ */
+/*#define HAS_SIGINFO_SI_BAND  / **/
+
+/* HAS_SIGINFO_SI_VALUE:
+ *     This symbol, if defined, indicates that siginfo_t has the
+ *     si_value member
+ */
+/*#define HAS_SIGINFO_SI_VALUE / **/
+
 /* HAS_SIGSETJMP:
  *     This variable indicates to the C program that the sigsetjmp()
  *     routine is available to save the calling process's registers
 #endif
 
 /* Generated from:
- * 056bddc3ae72075045127f87d3418b2caa44b81bdac54fa0a1a3cf11c8fbdd4a config_h.SH
- * a44240b1f83708d59d68e3c6d4d37d0c55ea9a2bab6e0413c17236c9000df18d uconfig.sh
+ * 0459b706f70bb18d7481b187553e0719406d2c7d5c354c3a309332dfd8e66197 config_h.SH
+ * 9382cd0e3b112993f14cfefe78ebe24b4b09df9d9dd199226ca7ba5e6b90f21a uconfig.sh
  * ex: set ro: */
index c705090..beecfe7 100644 (file)
@@ -439,6 +439,13 @@ d_shmctl='undef'
 d_shmdt='undef'
 d_shmget='undef'
 d_sigaction='undef'
+d_siginfo_si_addr='undef'
+d_siginfo_si_band='undef'
+d_siginfo_si_errno='undef'
+d_siginfo_si_pid='undef'
+d_siginfo_si_status='undef'
+d_siginfo_si_uid='undef'
+d_siginfo_si_value='undef'
 d_signbit='undef'
 d_sigprocmask='undef'
 d_sigsetjmp='undef'
index 8835d61..3e58288 100644 (file)
@@ -440,6 +440,13 @@ d_shmctl='undef'
 d_shmdt='undef'
 d_shmget='undef'
 d_sigaction='undef'
+d_siginfo_si_addr='undef'
+d_siginfo_si_band='undef'
+d_siginfo_si_errno='undef'
+d_siginfo_si_pid='undef'
+d_siginfo_si_status='undef'
+d_siginfo_si_uid='undef'
+d_siginfo_si_value='undef'
 d_signbit='undef'
 d_sigprocmask='undef'
 d_sigsetjmp='undef'
index 2c978a5..e18506f 100644 (file)
@@ -488,6 +488,13 @@ d_shmctl='undef'
 d_shmdt='undef'
 d_shmget='undef'
 d_sigaction='undef'
+d_siginfo_si_addr='undef'
+d_siginfo_si_band='undef'
+d_siginfo_si_errno='undef'
+d_siginfo_si_pid='undef'
+d_siginfo_si_status='undef'
+d_siginfo_si_uid='undef'
+d_siginfo_si_value='undef'
 d_signbit='undef'
 d_sigprocmask='undef'
 d_sigsetjmp='undef'
index 7b37e54..390be9b 100644 (file)
@@ -488,6 +488,13 @@ d_shmctl='undef'
 d_shmdt='undef'
 d_shmget='undef'
 d_sigaction='undef'
+d_siginfo_si_addr='undef'
+d_siginfo_si_band='undef'
+d_siginfo_si_errno='undef'
+d_siginfo_si_pid='undef'
+d_siginfo_si_status='undef'
+d_siginfo_si_uid='undef'
+d_siginfo_si_value='undef'
 d_signbit='undef'
 d_sigprocmask='undef'
 d_sigsetjmp='undef'
index 8bf7fba..aa79d2b 100644 (file)
@@ -488,6 +488,13 @@ d_shmctl='undef'
 d_shmdt='undef'
 d_shmget='undef'
 d_sigaction='undef'
+d_siginfo_si_addr='undef'
+d_siginfo_si_band='undef'
+d_siginfo_si_errno='undef'
+d_siginfo_si_pid='undef'
+d_siginfo_si_status='undef'
+d_siginfo_si_uid='undef'
+d_siginfo_si_value='undef'
 d_signbit='undef'
 d_sigprocmask='undef'
 d_sigsetjmp='undef'