[pypy-commit] pypy default: a failing test for the signals_enabled context manager's fork logic
bdkearns
noreply at buildbot.pypy.org
Sat Feb 16 09:41:50 CET 2013
Author: Brian Kearns <bdkearns at gmail.com>
Branch:
Changeset: r61304:320c4790eae6
Date: 2013-02-16 02:26 -0500
http://bitbucket.org/pypy/pypy/changeset/320c4790eae6/
Log: a failing test for the signals_enabled context manager's fork logic
diff --git a/pypy/module/__pypy__/test/test_signal.py b/pypy/module/__pypy__/test/test_signal.py
--- a/pypy/module/__pypy__/test/test_signal.py
+++ b/pypy/module/__pypy__/test/test_signal.py
@@ -1,5 +1,7 @@
import sys
+from pypy.module.thread.test.support import GenericTestThread
+
class AppTestMinimal:
spaceconfig = dict(usemodules=['__pypy__'])
@@ -11,7 +13,7 @@
# assert did not crash
-class AppTestThreadSignal:
+class AppTestThreadSignal(GenericTestThread):
spaceconfig = dict(usemodules=['__pypy__', 'thread', 'signal', 'time'])
def test_enable_signals(self):
@@ -48,6 +50,37 @@
finally:
__pypy__.thread._signals_enter()
+ def test_thread_fork_signals(self):
+ import __pypy__
+ import os, thread, signal
+
+ if not hasattr(os, 'fork'):
+ skip("No fork on this platform")
+
+ def fork():
+ with __pypy__.thread.signals_enabled:
+ return os.fork()
+
+ def threadfunction():
+ pid = fork()
+ if pid == 0:
+ print 'in child'
+ # signal() only works from the 'main' thread
+ signal.signal(signal.SIGUSR1, signal.SIG_IGN)
+ os._exit(42)
+ else:
+ self.timeout_killer(pid, 5)
+ exitcode = os.waitpid(pid, 0)[1]
+ feedback.append(exitcode)
+
+ feedback = []
+ thread.start_new_thread(threadfunction, ())
+ self.waitfor(lambda: feedback)
+ # if 0, an (unraisable) exception was raised from the forked thread.
+ # if 9, process was killed by timer.
+ # if 42<<8, os._exit(42) was correctly reached.
+ assert feedback == [42<<8]
+
class AppTestThreadSignalLock:
spaceconfig = dict(usemodules=['__pypy__', 'thread', 'signal'])
diff --git a/pypy/module/thread/threadlocals.py b/pypy/module/thread/threadlocals.py
--- a/pypy/module/thread/threadlocals.py
+++ b/pypy/module/thread/threadlocals.py
@@ -81,6 +81,16 @@
# (which are now dead); and for the current thread, force an
# enable_signals() if necessary. That's a hack but I cannot
# figure out a non-hackish way to handle thread+signal+fork :-(
+ """
+ TODO: this logic is currently flawed as we need to differentiate
+ between: 1) fork while in a main thread, in which case old should
+ not be incremented
+ 2) fork while in a subthread that has an enable_threads
+ context but is not main (in which case old should be
+ incremented, as the thread should get a point for becoming
+ the new 'main', so it remains in the dict when all its
+ contexts exit)
+ """
ident = rthread.get_ident()
old = self._signalsenabled.get(ident, 0)
self._signalsenabled.clear()
More information about the pypy-commit
mailing list