Skip to content

Commit 4717ee3

Browse files
author
Anselm Kruis
committed
merge 3.4-slp (Stackless python#81, python#85)
2 parents 7f98bf6 + 6f573bd commit 4717ee3

File tree

8 files changed

+55
-32
lines changed

8 files changed

+55
-32
lines changed

Stackless/changelog.txt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,8 @@ What's New in Stackless 3.X.X?
3434
- https://bitbucket.org/stackless-dev/stackless/issues/81
3535
Fix (crash) bugs during thread and interpreter shutdown.
3636
If a thread dies, Stackless now really kills tasklets with C-state. During
37-
interpreter shutdown, Stackless also kills daemon threads, if they execute
38-
Python code or switch tasklets. This change avoids crashes during a later
39-
shutdown stage.
37+
interpreter shutdown, Stackless also kills daemon threads, if they switch
38+
tasklets. This change avoids crashes during a later shutdown stage.
4039

4140
- https://bitbucket.org/stackless-dev/stackless/issues/92
4241
If you run Stackless with the option '-v' (or set the environment variable

Stackless/core/stacklesseval.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -516,9 +516,6 @@ void slp_kill_tasks_with_stacks(PyThreadState *target_ts)
516516
*/
517517
count++;
518518
kill_pending_current_main_and_watchdogs(ts);
519-
/* It helps to inactivate threads reliably */
520-
if (PyExc_TaskletExit)
521-
PyThreadState_SetAsyncExc(ts->thread_id, PyExc_TaskletExit);
522519
}
523520
}
524521
/* We must not release the GIL while we might hold the HEAD-lock.

Stackless/test/test_interpreter_shutdown.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import sys
33
import _thread as thread
44
import stackless
5-
import codecs
5+
import builtins
66
import os
77
import time
88
import collections
@@ -63,13 +63,14 @@ def __init__(self, out, checks, tasklets):
6363
self.checks = checks
6464
self.tasklets = tasklets
6565

66-
# register the detector in the codecs search path
67-
# it will be cleared after clearing the thread states
68-
# this way the detector runs very late
69-
def dummy_codecs_search_function(name):
70-
return None
71-
codecs.register(dummy_codecs_search_function)
72-
dummy_codecs_search_function.x = self
66+
# In Py_Finalize() the PyImport_Cleanup() runs shortly after
67+
# slp_kill_tasks_with_stacks(NULL).
68+
# As very first action of PyImport_Cleanup() the Python
69+
# interpreter sets builtins._ to None.
70+
# Therefore we can use this assignment to trigger the execution
71+
# of this detector. At this point the interpreter is still almost fully
72+
# intact.
73+
builtins._ = self
7374

7475
def __del__(self):
7576
if self.debug:

Stackless/unittests/test_defects.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44
import gc
55
import sys
66
import types
7-
import threading
7+
try:
8+
import threading
9+
withThreads = True
10+
except:
11+
withThreads = False
812

913
from stackless import _test_nostacklesscall as apply
1014
from support import StacklessTestCase, captured_stderr, require_one_thread
@@ -81,6 +85,7 @@ def TaskletFunc(self):
8185
hex(id(self.TaskletWithDelAndCollect(TaskletFunc)(self)))
8286
stackless.run() # crash here
8387

88+
@unittest.skipUnless(withThreads, "requires thread support")
8489
def test_tasklet_dealloc_in_thread_shutdown(self):
8590
# Test for https://bitbucket.org/stackless-dev/stackless/issues/89
8691
def other_thread_main():
@@ -298,6 +303,7 @@ def func():
298303
"""])
299304
self.assertEqual(rc, 42)
300305

306+
@unittest.skipUnless(withThreads, "requires thread support")
301307
def test_interthread_kill(self):
302308
# test for issue #87 https://bitbucket.org/stackless-dev/stackless/issues/87/
303309
import subprocess
@@ -358,6 +364,7 @@ def other_thread_main(self):
358364
"""])
359365
self.assertEqual(rc, 42)
360366

367+
@unittest.skipUnless(withThreads, "requires thread support")
361368
def test_tasklet_end_with_wrong_recursion_level(self):
362369
# test for issue #91 https://bitbucket.org/stackless-dev/stackless/issues/91/
363370
"""A test for issue #91, wrong recursion level after tasklet re-binding

Stackless/unittests/test_miscell.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,21 @@
55
import stackless
66
import sys
77
import traceback
8-
import contextlib
98
import weakref
109
import types
11-
import _thread as thread
10+
import contextlib
1211
import time
1312
import os
1413
from stackless import _test_nostacklesscall as apply
15-
16-
from support import StacklessTestCase, AsTaskletTestCase, require_one_thread
1714
try:
15+
import _thread as thread
1816
import threading
1917
withThreads = True
2018
except:
2119
withThreads = False
2220

21+
from support import StacklessTestCase, AsTaskletTestCase, require_one_thread
22+
2323

2424
def is_soft():
2525
softswitch = stackless.enable_softswitch(0)
@@ -504,6 +504,7 @@ def task():
504504
self.assertFalse(t.alive)
505505
self.assertEqual(t.thread_id, stackless.current.thread_id)
506506

507+
@unittest.skipUnless(withThreads, "requires thread support")
507508
@require_one_thread
508509
def test_kill_thread_without_main_tasklet(self):
509510
# this test depends on a race condition.
@@ -607,15 +608,19 @@ def other_thread_main():
607608
tlet.remove()
608609
tlet.kill()
609610

611+
@unittest.skipUnless(withThreads, "requires thread support")
610612
def test_kill_without_thread_state_nl0(self):
611613
return self._test_kill_without_thread_state(0, False)
612614

615+
@unittest.skipUnless(withThreads, "requires thread support")
613616
def test_kill_without_thread_state_nl1(self):
614617
return self._test_kill_without_thread_state(1, False)
615618

619+
@unittest.skipUnless(withThreads, "requires thread support")
616620
def test_kill_without_thread_state_blocked_nl0(self):
617621
return self._test_kill_without_thread_state(0, True)
618622

623+
@unittest.skipUnless(withThreads, "requires thread support")
619624
def test_kill_without_thread_state_blocked_nl1(self):
620625
return self._test_kill_without_thread_state(1, True)
621626

@@ -1011,6 +1016,7 @@ def test_bind_args_not_runnable(self):
10111016
self.assertFalse(t.scheduled)
10121017
t.run()
10131018

1019+
@unittest.skipUnless(withThreads, "requires thread support")
10141020
def test_unbind_main(self):
10151021
self.skipUnlessSoftswitching()
10161022

@@ -1034,6 +1040,7 @@ def other_thread():
10341040
t.join()
10351041
self.assertTrue(done[0])
10361042

1043+
@unittest.skipUnless(withThreads, "requires thread support")
10371044
def test_rebind_main(self):
10381045
# rebind the main tasklet of a thread. This is highly discouraged,
10391046
# because it will deadlock, if the thread is a non daemon threading.Thread.
@@ -1086,6 +1093,7 @@ def test():
10861093
self.assertEqual(tlet.recursion_depth, 0)
10871094
self.assertEqual(self.recursion_depth_in_test, 1)
10881095

1096+
@unittest.skipUnless(withThreads, "requires thread support")
10891097
def test_unbind_fail_cstate_no_thread(self):
10901098
# https://bitbucket.org/stackless-dev/stackless/issues/92
10911099
loop = True

Stackless/unittests/test_shutdown.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,24 @@
3434

3535
from __future__ import print_function, absolute_import, division
3636
import sys
37-
import _thread as thread
3837
import stackless
39-
import codecs
38+
import builtins
4039
import os
4140
import time
4241
import collections
4342
import unittest
44-
import threading
4543
import subprocess
4644
from stackless import _test_nostacklesscall as apply
45+
try:
46+
import _thread as thread
47+
import threading
48+
withThreads = True
49+
except:
50+
withThreads = False
4751
from support import StacklessTestCase
4852

4953

54+
@unittest.skipUnless(withThreads, "requires thread support")
5055
class TestThreadShutdown(StacklessTestCase):
5156

5257
def _test_thread_shutdown(self, func, expect_kill):
@@ -125,6 +130,8 @@ class TestInterpreterShutdown(unittest.TestCase):
125130

126131
def _test_shutdown_with_thread(self, case, is_hard, allowed_errors=(), debug=False):
127132
# test for issue #81 https://bitbucket.org/stackless-dev/stackless/issues/81/
133+
if not withThreads:
134+
self.skipTest("requires thread support")
128135
script = __file__
129136
if script.endswith("pyc") or script.endswith("pyo"):
130137
script = script[:-1]
@@ -213,13 +220,14 @@ def __init__(self, out, checks, tasklets):
213220
self.checks = checks
214221
self.tasklets = tasklets
215222

216-
# register the detector in the codecs search path
217-
# it will be cleared after clearing the thread states
218-
# this way the detector runs very late
219-
def dummy_codecs_search_function(name):
220-
return None
221-
codecs.register(dummy_codecs_search_function)
222-
dummy_codecs_search_function.x = self
223+
# In Py_Finalize() the PyImport_Cleanup() runs shortly after
224+
# slp_kill_tasks_with_stacks(NULL).
225+
# As very first action of PyImport_Cleanup() the Python
226+
# interpreter sets builtins._ to None.
227+
# Therefore we can use this assignment to trigger the execution
228+
# of this detector. At this point the interpreter is still almost fully
229+
# intact.
230+
builtins._ = self
223231

224232
def __del__(self):
225233
if self.debug:
@@ -398,7 +406,7 @@ def interpreter_shutdown_test():
398406
test = Test()
399407
detector = Detector(test.out, test.checks, test.tasklets)
400408
assert sys.getrefcount(detector) - sys.getrefcount(object()) == 2
401-
detector = None # the last ref is now in the codecs search path
409+
detector = None # the last ref is now in bultins._
402410
thread.start_new_thread(test.other_thread_main, ())
403411
ready.acquire() # Be sure the other thread is ready.
404412
# print("at end")

Stackless/unittests/test_thread.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
withThreads = True
1717
except:
1818
withThreads = False
19+
class threading(object):
20+
Thread = object
1921

2022

2123
class SkipMixin(object):
@@ -278,6 +280,7 @@ def test_rebind_nontrivial(self):
278280
end()
279281

280282

283+
@unittest.skipUnless(withThreads, "requires thread support")
281284
class RemoteTaskletTests(SkipMixin, StacklessTestCase):
282285
ThreadClass = LingeringThread
283286

Stackless/unittests/test_watchdog.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ def tearDown(self):
440440
except AssertionError:
441441
self.watchdog_list[0] = None
442442
self.watchdog_list[1:] = []
443+
raise
443444
super(TestNewWatchdog, self).tearDown()
444445

445446
def test_run_from_worker(self):
@@ -559,7 +560,7 @@ def runner_func():
559560

560561
def task():
561562
while True:
562-
for i in range(200):
563+
for i in range(500):
563564
i = i
564565
stackless.schedule()
565566

@@ -607,7 +608,6 @@ def task():
607608
stackless.run()
608609
self.assertEqual(self.done, 2)
609610

610-
@unittest.skip("issue #85, assertion violation")
611611
def test_watchdog_priority_soft(self):
612612
"""Verify that outermost "real" watchdog gets awoken"""
613613
self._test_watchdog_priority(True)

0 commit comments

Comments
 (0)