@@ -247,6 +247,9 @@ class TestChildProcessCleanup:
247247
248248 @pytest .mark .anyio
249249 @pytest .mark .filterwarnings ("ignore::ResourceWarning" if sys .platform == "win32" else "default" )
250+ @pytest .mark .filterwarnings (
251+ "ignore::pytest.PytestUnraisableExceptionWarning" if sys .platform == "win32" else "default"
252+ )
250253 async def test_basic_child_process_cleanup (self ):
251254 """Test basic parent-child process cleanup.
252255 Parent spawns a single child process that writes continuously to a file.
@@ -314,17 +317,16 @@ async def test_basic_child_process_cleanup(self):
314317 print ("Terminating process and children..." )
315318 await _terminate_process_tree (proc )
316319
317- # Verify processes stopped
318- await anyio .sleep (0.5 )
319- if os .path .exists (marker_file ): # pragma: no branch
320- size_after_cleanup = os .path .getsize (marker_file )
321- await anyio .sleep (0.5 )
322- final_size = os .path .getsize (marker_file )
323-
324- print (f"After cleanup: file size { size_after_cleanup } -> { final_size } " )
325- assert final_size == size_after_cleanup , (
326- f"Child process still running! File grew by { final_size - size_after_cleanup } bytes"
327- )
320+ # Verify processes stopped — poll with retries for slow CI runners
321+ with anyio .fail_after (5 ):
322+ if os .path .exists (marker_file ): # pragma: no branch
323+ while True :
324+ size_after_cleanup = os .path .getsize (marker_file )
325+ await anyio .sleep (0.5 )
326+ final_size = os .path .getsize (marker_file )
327+ if final_size == size_after_cleanup :
328+ print (f"After cleanup: file stopped at { final_size } bytes" )
329+ break
328330
329331 print ("SUCCESS: Child process was properly terminated" )
330332
@@ -338,6 +340,9 @@ async def test_basic_child_process_cleanup(self):
338340
339341 @pytest .mark .anyio
340342 @pytest .mark .filterwarnings ("ignore::ResourceWarning" if sys .platform == "win32" else "default" )
343+ @pytest .mark .filterwarnings (
344+ "ignore::pytest.PytestUnraisableExceptionWarning" if sys .platform == "win32" else "default"
345+ )
341346 async def test_nested_process_tree (self ):
342347 """Test nested process tree cleanup (parent → child → grandchild).
343348 Each level writes to a different file to verify all processes are terminated.
@@ -412,14 +417,20 @@ async def test_nested_process_tree(self):
412417 # Terminate the whole tree
413418 await _terminate_process_tree (proc )
414419
415- # Verify all stopped
416- await anyio .sleep (0.5 )
417- for file_path , name in [(parent_file , "parent" ), (child_file , "child" ), (grandchild_file , "grandchild" )]:
418- if os .path .exists (file_path ): # pragma: no branch
419- size1 = os .path .getsize (file_path )
420- await anyio .sleep (0.3 )
421- size2 = os .path .getsize (file_path )
422- assert size1 == size2 , f"{ name } still writing after cleanup!"
420+ # Verify all stopped — poll with retries for slow CI runners
421+ with anyio .fail_after (5 ):
422+ for file_path , name in [
423+ (parent_file , "parent" ),
424+ (child_file , "child" ),
425+ (grandchild_file , "grandchild" ),
426+ ]:
427+ if os .path .exists (file_path ): # pragma: no branch
428+ while True :
429+ size1 = os .path .getsize (file_path )
430+ await anyio .sleep (0.5 )
431+ size2 = os .path .getsize (file_path )
432+ if size1 == size2 :
433+ break
423434
424435 print ("SUCCESS: All processes in tree terminated" )
425436
@@ -433,6 +444,9 @@ async def test_nested_process_tree(self):
433444
434445 @pytest .mark .anyio
435446 @pytest .mark .filterwarnings ("ignore::ResourceWarning" if sys .platform == "win32" else "default" )
447+ @pytest .mark .filterwarnings (
448+ "ignore::pytest.PytestUnraisableExceptionWarning" if sys .platform == "win32" else "default"
449+ )
436450 async def test_early_parent_exit (self ):
437451 """Test cleanup when parent exits during termination sequence.
438452 Tests the race condition where parent might die during our termination
@@ -490,13 +504,15 @@ def handle_term(sig, frame):
490504 # Terminate - this will kill the process group even if parent exits first
491505 await _terminate_process_tree (proc )
492506
493- # Verify child stopped
494- await anyio .sleep (0.5 )
495- if os .path .exists (marker_file ): # pragma: no branch
496- size3 = os .path .getsize (marker_file )
497- await anyio .sleep (0.3 )
498- size4 = os .path .getsize (marker_file )
499- assert size3 == size4 , "Child should be terminated"
507+ # Verify child stopped — poll with retries for slow CI runners
508+ with anyio .fail_after (5 ):
509+ if os .path .exists (marker_file ): # pragma: no branch
510+ while True :
511+ size3 = os .path .getsize (marker_file )
512+ await anyio .sleep (0.5 )
513+ size4 = os .path .getsize (marker_file )
514+ if size3 == size4 :
515+ break
500516
501517 print ("SUCCESS: Child terminated even with parent exit during cleanup" )
502518
0 commit comments