[issue12625] sporadic test_unittest failure
Charles-François Natali
report at bugs.python.org
Sun Jul 24 14:32:31 CEST 2011
Charles-François Natali <neologix at free.fr> added the comment:
> No, it's a feature of the new GIL.
When I look at 2.7's code, I see something different - _Py_Ticker is
reset in Py_AddPendingCall():
int
Py_AddPendingCall(int (*func)(void *), void *arg)
{
[...]
/* signal main loop */
_Py_Ticker = 0;
pendingcalls_to_do = 1;
[...]
}
And there's a comment in the main eval loop which confirms this:
/* Do periodic things. Doing this every time through
the loop would add too much overhead, so we do it
only every Nth instruction. We also do it if
``pendingcalls_to_do'' is set, i.e. when an asynchronous
event needs attention (e.g. a signal handler or
async I/O handler); see Py_AddPendingCall() and
Py_MakePendingCalls() above. */
So, AFAICT, signal handlers will get called right away (and if I
remove the _Py_Ticker reset from Py_AddPendingCall(), then those tests
fail consistently on Linux).
Or am I missing something?
Concerning the original problem, here's a patch implementing the second idea:
- getpid() is called after each kill(getpid(), <signum>), to "force"
the signal delivery
- the test is now re-enabled on FreeBSD6
I think this should fx the problem on both FreeBSD6 and OpenSolaris,
but since I don't have a FreeBSD or OpenSolaris box at hand, I
couldn't test it. Shall I try to commit it and see what the buildbots
say?
----------
Added file: http://bugs.python.org/file22743/kill_delayed_signal.diff
_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue12625>
_______________________________________
-------------- next part --------------
diff -r cda93720c06d Lib/unittest/test/test_break.py
--- a/Lib/unittest/test/test_break.py Sat Jul 23 18:15:43 2011 +0200
+++ b/Lib/unittest/test/test_break.py Sun Jul 24 14:23:32 2011 +0200
@@ -10,8 +10,6 @@
@unittest.skipUnless(hasattr(os, 'kill'), "Test requires os.kill")
@unittest.skipIf(sys.platform =="win32", "Test cannot run on Windows")
- at unittest.skipIf(sys.platform == 'freebsd6', "Test kills regrtest on freebsd6 "
- "if threads have been used")
class TestBreak(unittest.TestCase):
def setUp(self):
@@ -29,8 +27,15 @@
self.assertNotEqual(signal.getsignal(signal.SIGINT), default_handler)
try:
+ # When a process sends a signal to itself, POSIX states that the
+ # signal must be delivered before the kill() syscall returns. Some
+ # operating systems are known to delay signal delivery in this
+ # situation (see issues #12625, #8263 and #12469): to force the
+ # signal's delivery, we make a dummy getpid() syscall (signals are
+ # typically delivered when the process returns to user-space).
pid = os.getpid()
os.kill(pid, signal.SIGINT)
+ os.getpid()
except KeyboardInterrupt:
self.fail("KeyboardInterrupt not handled")
@@ -61,6 +66,7 @@
def test(result):
pid = os.getpid()
os.kill(pid, signal.SIGINT)
+ os.getpid()
result.breakCaught = True
self.assertTrue(result.shouldStop)
@@ -79,9 +85,11 @@
def test(result):
pid = os.getpid()
os.kill(pid, signal.SIGINT)
+ os.getpid()
result.breakCaught = True
self.assertTrue(result.shouldStop)
os.kill(pid, signal.SIGINT)
+ os.getpid()
self.fail("Second KeyboardInterrupt not raised")
try:
@@ -109,6 +117,7 @@
def test(result):
pid = os.getpid()
os.kill(pid, signal.SIGINT)
+ os.getpid()
try:
test(result)
@@ -134,6 +143,7 @@
try:
pid = os.getpid()
os.kill(pid, signal.SIGINT)
+ os.getpid()
except KeyboardInterrupt:
pass
else:
@@ -173,6 +183,7 @@
try:
pid = os.getpid()
os.kill(pid, signal.SIGINT)
+ os.getpid()
except KeyboardInterrupt:
pass
More information about the Python-bugs-list
mailing list