summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd Rinaldo <toddr@cpan.org>2020-01-30 11:53:31 -0600
committerTodd Rinaldo <toddr@cpan.org>2020-02-04 13:32:37 -0600
commit92d4124ba4c1d1465a3a7cd6ae35bb0ad116b073 (patch)
tree1427fddfc0334132cd9162dbfed1ecc3a3096806
parent34d254cefc451e5ab438acf22a51d7b557c05a0e (diff)
downloadperl-92d4124ba4c1d1465a3a7cd6ae35bb0ad116b073.tar.gz
Pass the canonical signal name to the signal handler when it is invoked.
Prior to this change, when a signal handler was invoked, the signame passed into the sub would be the name of the signal that was defined first via {}. This meant that the handler had to either be aware of the duplicates and handle things appropriately or it would be at the mercy of action at a distance the handler might be unaware of. This change assures a consistent signal name for now on. It should be the first signal listed in $Config{sig_name}. Duplicates are listed at the end.
-rw-r--r--MANIFEST1
-rw-r--r--mg.c3
-rw-r--r--t/op/signame_canonical.t74
3 files changed, 77 insertions, 1 deletions
diff --git a/MANIFEST b/MANIFEST
index 1bbab6c850..af08498565 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -5918,6 +5918,7 @@ t/op/runlevel.t See if die() works from perl_call_*()
t/op/select.t See if 0- and 1-argument select works
t/op/setpgrpstack.t See if setpgrp works
t/op/sigdispatch.t See if signals are always dispatched
+t/op/signame_canonical.t See if duplicate signal names always use the canonical name when the handler is invoked.
t/op/signatures.t See if sub signatures work
t/op/sigsystem.t See if system and SIGCHLD handlers play together nicely
t/op/sleep.t See if sleep works
diff --git a/mg.c b/mg.c
index 37d734ddd1..cd1f57de5a 100644
--- a/mg.c
+++ b/mg.c
@@ -1753,7 +1753,8 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
Ideally we'd find some way of making SVs at (C) compile time, or
at least, doing most of the work. */
if (!PL_psig_name[i]) {
- PL_psig_name[i] = newSVpvn(s, len);
+ const char* name = PL_sig_name[i];
+ PL_psig_name[i] = newSVpvn(name, strlen(name));
SvREADONLY_on(PL_psig_name[i]);
}
} else {
diff --git a/t/op/signame_canonical.t b/t/op/signame_canonical.t
new file mode 100644
index 0000000000..abd77328fa
--- /dev/null
+++ b/t/op/signame_canonical.t
@@ -0,0 +1,74 @@
+#!perl -w
+
+# We assume that TestInit has been used.
+
+BEGIN {
+ chdir 't' if -d 't';
+ require './test.pl';
+}
+
+use strict;
+use warnings;
+
+use Config;
+use Data::Dumper;
+$Data::Dumper::Sortkeys = 1;
+
+# Windows doesn't seem to be able to test signals.
+skip_all("Signals lock up tests on $^O") if $^O =~ /MSWin32/;
+
+$| = 1;
+
+# Extract the signals from %Config.
+my @SIGNAMES = split /\s+/, $Config{sig_name};
+my @SIGNUMS = split /\s+/, $Config{sig_num};
+
+my %SIG_MAP;
+foreach my $i ( 0 .. ( scalar @SIGNAMES - 1 ) ) {
+ $SIG_MAP{ $SIGNAMES[$i] } = $SIGNUMS[$i];
+}
+
+# Find the canonical (first) signal names.
+my %CANONICAL_SIG;
+my @duplicate_signals;
+foreach my $sig (@SIGNAMES) {
+ my $signum = $SIG_MAP{$sig};
+ $CANONICAL_SIG{$signum} //= $sig;
+ push @duplicate_signals, $sig if $CANONICAL_SIG{$signum} ne $sig;
+}
+
+plan tests => scalar @duplicate_signals * 5;
+watchdog(25);
+
+# Define the duplicate signal handlers.
+my $sent = '';
+
+sub handler_is {
+ my $signame = shift;
+ my $signum = $SIG_MAP{$signame};
+
+ my $canonical = $CANONICAL_SIG{$signum};
+
+ is( $signame, $canonical, "Signal name for $sent is recieved as the canonical '$canonical' name." );
+
+ return;
+}
+
+foreach my $dupe (@duplicate_signals) {
+ my $canonical_name = $CANONICAL_SIG{ $SIG_MAP{$dupe} };
+ note "Testing $dupe / $canonical_name signal pair";
+ {
+ local $SIG{$dupe} = \&handler_is;
+ is( $SIG{$dupe}, $SIG{$canonical_name}, "Both handlers for $canonical_name/$dupe are set" );
+
+ $sent = $dupe;
+ kill $dupe, $$;
+
+ $sent = $canonical_name;
+ kill $canonical_name, $$;
+ }
+
+ is( $SIG{$dupe}, undef, "The signal $dupe is cleared after local goes out of scope." );
+ is( $SIG{$canonical_name}, undef, "The signal $canonical_name is cleared after local goes out of scope." );
+}
+