[pypy-svn] pypy default: Fix siginterrupt(). Previously, the state would be reset
arigo
commits-noreply at bitbucket.org
Sun Feb 13 11:25:38 CET 2011
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r41870:a944602ffc05
Date: 2011-02-13 11:25 +0100
http://bitbucket.org/pypy/pypy/changeset/a944602ffc05/
Log: Fix siginterrupt(). Previously, the state would be reset to default
after the first time the signal was received.
diff --git a/pypy/module/signal/test/test_signal.py b/pypy/module/signal/test/test_signal.py
--- a/pypy/module/signal/test/test_signal.py
+++ b/pypy/module/signal/test/test_signal.py
@@ -197,11 +197,35 @@
signal.signal(signal.SIGUSR1, signal.SIG_DFL)
def test_siginterrupt(self):
- import signal
+ import signal, os, time
signum = signal.SIGUSR1
+ def readpipe_is_not_interrupted():
+ # from CPython's test_signal.readpipe_interrupted()
+ r, w = os.pipe()
+ ppid = os.getpid()
+ pid = os.fork()
+ if pid == 0:
+ try:
+ time.sleep(1)
+ os.kill(ppid, signum)
+ time.sleep(1)
+ finally:
+ os._exit(0)
+ else:
+ try:
+ os.close(w)
+ # we expect not to be interrupted. If we are, the
+ # following line raises OSError(EINTR).
+ os.read(r, 1)
+ finally:
+ os.waitpid(pid, 0)
+ os.close(r)
+ #
oldhandler = signal.signal(signum, lambda x,y: None)
try:
signal.siginterrupt(signum, 0)
+ readpipe_is_not_interrupted()
+ readpipe_is_not_interrupted()
finally:
signal.signal(signum, oldhandler)
diff --git a/pypy/module/signal/interp_signal.py b/pypy/module/signal/interp_signal.py
--- a/pypy/module/signal/interp_signal.py
+++ b/pypy/module/signal/interp_signal.py
@@ -35,6 +35,7 @@
include_dirs = [str(py.path.local(autopath.pypydir).join('translator', 'c'))],
export_symbols = ['pypysig_poll', 'pypysig_default',
'pypysig_ignore', 'pypysig_setflag',
+ 'pypysig_reinstall',
'pypysig_set_wakeup_fd',
'pypysig_getaddr_occurred'],
)
@@ -65,6 +66,7 @@
pypysig_ignore = external('pypysig_ignore', [rffi.INT], lltype.Void)
pypysig_default = external('pypysig_default', [rffi.INT], lltype.Void)
pypysig_setflag = external('pypysig_setflag', [rffi.INT], lltype.Void)
+pypysig_reinstall = external('pypysig_reinstall', [rffi.INT], lltype.Void)
pypysig_set_wakeup_fd = external('pypysig_set_wakeup_fd', [rffi.INT], rffi.INT)
pypysig_poll = external('pypysig_poll', [], rffi.INT, threadsafe=False)
# don't bother releasing the GIL around a call to pypysig_poll: it's
@@ -150,7 +152,7 @@
except KeyError:
return # no handler, ignore signal
# re-install signal handler, for OSes that clear it
- pypysig_setflag(n)
+ pypysig_reinstall(n)
# invoke the app-level handler
space = self.space
ec = space.getexecutioncontext()
diff --git a/pypy/translator/c/src/signals.h b/pypy/translator/c/src/signals.h
--- a/pypy/translator/c/src/signals.h
+++ b/pypy/translator/c/src/signals.h
@@ -143,6 +143,21 @@
#endif
}
+void pypysig_reinstall(int signum)
+{
+#ifdef SA_RESTART
+ /* Assume sigaction was used. We did not pass SA_RESETHAND to
+ sa_flags, so there is nothing to do here. */
+#else
+# ifdef SIGCHLD
+ /* To avoid infinite recursion, this signal remains
+ reset until explicitly re-instated. (Copied from CPython) */
+ if (signum != SIGCHLD)
+# endif
+ pypysig_setflag(signum);
+#endif
+}
+
int pypysig_poll(void)
{
if (pypysig_occurred)
More information about the Pypy-commit
mailing list