develooper Front page | perl.perl5.porters | Postings from January 2010

[PATCH] Restore errno if signal handler changes it

Thread Next
From:
lubo.rintel
Date:
January 28, 2010 06:53
Subject:
[PATCH] Restore errno if signal handler changes it
Message ID:
1264690392-14554-1-git-send-email-lubo.rintel@gooddata.com
From: Lubomir Rintel (GoodData) <lubo.rintel@v3.sk>

It's way too easy to forget to "local $!" in signal handlers and
changing $! when signal hits between two ops is probably never useful.

Alternate solution would be to push $! to savestack but i would be
functionally equivalent, I believe, just more heavy weight.
---
 MANIFEST         |    1 +
 mg.c             |    4 ++++
 t/lib/errnosig.t |   17 +++++++++++++++++
 3 files changed, 22 insertions(+), 0 deletions(-)
 create mode 100644 t/lib/errnosig.t

diff --git a/MANIFEST b/MANIFEST
index e34ef19..299076c 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -3440,6 +3440,7 @@ lib/English.t			See if English works
 lib/Env.pm			Map environment into ordinary variables
 lib/Env/t/array.t		See if Env works for arrays
 lib/Env/t/env.t			See if Env works
+lib/errnosig.t			Test case for restoration $! when leaving signal handlers
 lib/exceptions.pl		catch and throw routines
 lib/Exporter/Heavy.pm		Complicated routines for Exporter
 lib/Exporter.pm			Exporter base class
diff --git a/mg.c b/mg.c
index b9a1464..cac124a 100644
--- a/mg.c
+++ b/mg.c
@@ -1375,6 +1375,8 @@ Perl_despatch_signals(pTHX)
     PL_sig_pending = 0;
     for (sig = 1; sig < SIG_SIZE; sig++) {
 	if (PL_psig_pend[sig]) {
+	    int errno_save = errno;
+
 	    PERL_BLOCKSIG_ADD(set, sig);
  	    PL_psig_pend[sig] = 0;
 	    PERL_BLOCKSIG_BLOCK(set);
@@ -1384,6 +1386,8 @@ Perl_despatch_signals(pTHX)
 	    (*PL_sighandlerp)(sig);
 #endif
 	    PERL_BLOCKSIG_UNBLOCK(set);
+
+	    errno = errno_save;
 	}
     }
 }
diff --git a/t/lib/errnosig.t b/t/lib/errnosig.t
new file mode 100644
index 0000000..d87ac2f
--- /dev/null
+++ b/t/lib/errnosig.t
@@ -0,0 +1,17 @@
+#!./perl
+
+print "1..1\n";
+
+$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
+print (($! == -1 ? 'not ok' : 'ok')." 1 - Signal does not modify \$!\n");
-- 
1.6.6


Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About