Skip to content

Commit dd463fa

Browse files
authored
Fix flaky AsyncWrapper reset_state test on Python 3.14 (#39521)
1 parent 9c82e05 commit dd463fa

1 file changed

Lines changed: 13 additions & 2 deletions

File tree

sdks/python/apache_beam/transforms/async_dofn_test.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ def add_item(i):
489489
self.assertEqual(bag_states['key' + str(i)].items, [])
490490

491491
@staticmethod
492-
def _run_reset_state_concurrent_teardown(use_asyncio):
492+
def _run_reset_state_concurrent_teardown(use_asyncio, reset_started):
493493
dofn = BasicDofn(sleep_time=0.5)
494494
async_dofn = async_lib.AsyncWrapper(dofn, use_asyncio=use_asyncio)
495495
async_dofn.setup()
@@ -502,15 +502,26 @@ def _run_reset_state_concurrent_teardown(use_asyncio):
502502

503503
# Verify that calling reset_state() while background tasks are actively running
504504
# completes cleanly without causing lock-ordering deadlocks.
505+
reset_started.set()
505506
async_lib.AsyncWrapper.reset_state()
506507

507508
def test_reset_state_concurrent_teardown(self):
508509
# Verify concurrent teardown safety in a separate process to prevent any potential
509510
# regressions from freezing the main pytest process at exit.
511+
reset_started = multiprocessing.Event()
510512
p = multiprocessing.Process(
511513
target=AsyncTest._run_reset_state_concurrent_teardown,
512-
args=(self.use_asyncio, ))
514+
args=(self.use_asyncio, reset_started))
513515
p.start()
516+
517+
# Python 3.14 uses forkserver by default on POSIX. Wait for child startup
518+
# before measuring reset_state() so import and process startup time cannot
519+
# be mistaken for a teardown deadlock.
520+
if not reset_started.wait(timeout=30.0):
521+
p.terminate()
522+
p.join()
523+
self.fail("child process did not reach reset_state() before timeout")
524+
514525
p.join(timeout=10.0)
515526

516527
if p.is_alive():

0 commit comments

Comments
 (0)