@@ -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 ()
@@ -283,8 +299,32 @@ async def probe():
283
299
284
300
return "done"
285
301
286
-
287
- class WinPolicyTests (test_utils .TestCase ):
302
+ def test_loop_restart (self ):
303
+ # We're fishing for the "RuntimeError: <_overlapped.Overlapped object at XXX>
304
+ # still has pending operation at deallocation, the process may crash" error
305
+ stop = threading .Event ()
306
+ def threadMain ():
307
+ while not stop .is_set ():
308
+ self .loop .call_soon_threadsafe (lambda : None )
309
+ time .sleep (0.01 )
310
+ thr = threading .Thread (target = threadMain )
311
+
312
+ # In 10 60-second runs of this test prior to the fix:
313
+ # time in seconds until failure: (none), 15.0, 6.4, (none), 7.6, 8.3, 1.7, 22.2, 23.5, 8.3
314
+ # 10 seconds had a 50% failure rate but longer would be more costly
315
+ end_time = time .time () + 10 # Run for 10 seconds
316
+ self .loop .call_soon (thr .start )
317
+ while not self ._unraisable : # Stop if we got an unraisable exc
318
+ self .loop .stop ()
319
+ self .loop .run_forever ()
320
+ if time .time () >= end_time :
321
+ break
322
+
323
+ stop .set ()
324
+ thr .join ()
325
+
326
+
327
+ class WinPolicyTests (WindowsEventsTestCase ):
288
328
289
329
def test_selector_win_policy (self ):
290
330
async def main ():
0 commit comments