@@ -36,7 +36,23 @@ def data_received(self, data):
36
36
self .trans .close ()
37
37
38
38
39
- class ProactorLoopCtrlC (test_utils .TestCase ):
39
+ class WindowsEventsTestCase (test_utils .TestCase ):
40
+ def _unraisablehook (self , unraisable ):
41
+ # Storing unraisable.object can resurrect an object which is being
42
+ # finalized. Storing unraisable.exc_value creates a reference cycle.
43
+ self ._unraisable = unraisable
44
+ print (unraisable )
45
+
46
+ def setUp (self ):
47
+ self ._prev_unraisablehook = sys .unraisablehook
48
+ self ._unraisable = None
49
+ sys .unraisablehook = self ._unraisablehook
50
+
51
+ def tearDown (self ):
52
+ sys .unraisablehook = self ._prev_unraisablehook
53
+ self .assertIsNone (self ._unraisable )
54
+
55
+ class ProactorLoopCtrlC (WindowsEventsTestCase ):
40
56
41
57
def test_ctrl_c (self ):
42
58
@@ -58,7 +74,7 @@ def SIGINT_after_delay():
58
74
thread .join ()
59
75
60
76
61
- class ProactorMultithreading (test_utils . TestCase ):
77
+ class ProactorMultithreading (WindowsEventsTestCase ):
62
78
def test_run_from_nonmain_thread (self ):
63
79
finished = False
64
80
@@ -79,7 +95,7 @@ def func():
79
95
self .assertTrue (finished )
80
96
81
97
82
- class ProactorTests (test_utils . TestCase ):
98
+ class ProactorTests (WindowsEventsTestCase ):
83
99
84
100
def setUp (self ):
85
101
super ().setUp ()
@@ -239,8 +255,32 @@ def test_read_self_pipe_restart(self):
239
255
self .close_loop (self .loop )
240
256
self .assertFalse (self .loop .call_exception_handler .called )
241
257
242
-
243
- class WinPolicyTests (test_utils .TestCase ):
258
+ def test_loop_restart (self ):
259
+ # We're fishing for the "RuntimeError: <_overlapped.Overlapped object at XXX>
260
+ # still has pending operation at deallocation, the process may crash" error
261
+ stop = threading .Event ()
262
+ def threadMain ():
263
+ while not stop .is_set ():
264
+ self .loop .call_soon_threadsafe (lambda : None )
265
+ time .sleep (0.01 )
266
+ thr = threading .Thread (target = threadMain )
267
+
268
+ # In 10 60-second runs of this test prior to the fix:
269
+ # time in seconds until failure: (none), 15.0, 6.4, (none), 7.6, 8.3, 1.7, 22.2, 23.5, 8.3
270
+ # 10 seconds had a 50% failure rate but longer would be more costly
271
+ end_time = time .time () + 10 # Run for 10 seconds
272
+ self .loop .call_soon (thr .start )
273
+ while not self ._unraisable : # Stop if we got an unraisable exc
274
+ self .loop .stop ()
275
+ self .loop .run_forever ()
276
+ if time .time () >= end_time :
277
+ break
278
+
279
+ stop .set ()
280
+ thr .join ()
281
+
282
+
283
+ class WinPolicyTests (WindowsEventsTestCase ):
244
284
245
285
def test_selector_win_policy (self ):
246
286
async def main ():
0 commit comments