In perl.git, the branch blead has been updated <http://perl5.git.perl.org/perl.git/commitdiff/d016601746b09e0f0a7eb2148b6eb594d3992339?hp=1e8125c621275d18c74bc8dae3bfc3c03929fe1e>
- Log ----------------------------------------------------------------- commit d016601746b09e0f0a7eb2148b6eb594d3992339 Author: Lubomir Rintel <[email protected]> Date: Mon Jul 26 16:05:05 2010 +0200 Restore errno if signal handler changes it It's way too easy to forget to "local $!" in signal handlers and changing $! when signal hits between two ops is probably never useful. ----------------------------------------------------------------------- Summary of changes: MANIFEST | 1 + mg.c | 2 ++ t/io/errnosig.t | 30 ++++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 0 deletions(-) create mode 100644 t/io/errnosig.t diff --git a/MANIFEST b/MANIFEST index 22b1083..f48cc47 100644 --- a/MANIFEST +++ b/MANIFEST @@ -4275,6 +4275,7 @@ t/io/crlf_through.t See if pipe passes data intact with :crlf t/io/defout.t See if PL_defoutgv works t/io/dup.t See if >& works right t/io/errno.t See if $! is correctly set +t/io/errnosig.t Test case for restoration $! when leaving signal handlers t/io/fflush.t See if auto-flush on fork/exec/system/qx works t/io/fs.t See if directory manipulations work t/io/inplace.t See if inplace editing works diff --git a/mg.c b/mg.c index 47844e0..5eca2e5 100644 --- a/mg.c +++ b/mg.c @@ -1385,6 +1385,7 @@ Perl_despatch_signals(pTHX) PL_sig_pending = 0; for (sig = 1; sig < SIG_SIZE; sig++) { if (PL_psig_pend[sig]) { + dSAVE_ERRNO; PERL_BLOCKSIG_ADD(set, sig); PL_psig_pend[sig] = 0; PERL_BLOCKSIG_BLOCK(set); @@ -1394,6 +1395,7 @@ Perl_despatch_signals(pTHX) (*PL_sighandlerp)(sig); #endif PERL_BLOCKSIG_UNBLOCK(set); + RESTORE_ERRNO; } } } diff --git a/t/io/errnosig.t b/t/io/errnosig.t new file mode 100644 index 0000000..8effcf1 --- /dev/null +++ b/t/io/errnosig.t @@ -0,0 +1,30 @@ +#!./perl + +BEGIN { + chdir 't' if -d 't'; + @INC = qw(. ../lib); +} + +require Config; import Config; +require "test.pl"; +plan(tests => 1); + +SKIP: { + skip("Alarm not supported", 1) unless exists $Config{'d_alarm'}; + + $SIG{ALRM} = sub { + # We could call anything that modifies $! here, but + # this way we can be sure that it isn't the same + # errno as interrupted sleep() would return, and are + # able to check it thereafter. + $! = -1; + }; + + alarm 1; + sleep 2; + + # Interrupted sleeps sets errno to EAGAIN, but signal + # that # hits after it (if safe signal handling is enabled) + # causes a routing that modifies $! to be run afterwards + isnt($! + 0, -1, 'Signal does not modify $!'); +} -- Perl5 Master Repository
