This is an automated email from the ASF dual-hosted git repository.
potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 214f28fbaca Fix process_utils force-kill test race on Python 3.14
(#63792)
214f28fbaca is described below
commit 214f28fbacac8c1987ca7e06d7d1137f16fce117
Author: Dev-iL <[email protected]>
AuthorDate: Thu Mar 19 12:48:04 2026 +0200
Fix process_utils force-kill test race on Python 3.14 (#63792)
With 'forkserver' (Python 3.14 default on Linux), the child process
starts from a clean slate and needs time to import modules and execute
the target function before the SIGTERM-ignoring signal handlers are
installed. The old sleep(0) was not enough — SIGTERM could arrive
before the handlers were in place, killing the process before the test
reached the SIGKILL path.
Use a multiprocessing.Event to synchronize: the child signals readiness
only after its signal handlers are installed.
Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
---
airflow-core/tests/unit/utils/test_process_utils.py | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/airflow-core/tests/unit/utils/test_process_utils.py
b/airflow-core/tests/unit/utils/test_process_utils.py
index 47ffc9245f3..f45d8e4f636 100644
--- a/airflow-core/tests/unit/utils/test_process_utils.py
+++ b/airflow-core/tests/unit/utils/test_process_utils.py
@@ -137,9 +137,10 @@ def my_sleep_subprocess():
sleep(100)
-def my_sleep_subprocess_with_signals():
+def my_sleep_subprocess_with_signals(ready_event):
signal.signal(signal.SIGINT, lambda signum, frame: None)
signal.signal(signal.SIGTERM, lambda signum, frame: None)
+ ready_event.set()
sleep(100)
@@ -161,9 +162,14 @@ class TestKillChildProcessesByPids:
assert before_num_process == num_process
def test_should_force_kill_process(self, caplog):
- process =
multiprocessing.Process(target=my_sleep_subprocess_with_signals, args=())
+ ready_event = multiprocessing.Event()
+ process =
multiprocessing.Process(target=my_sleep_subprocess_with_signals,
args=(ready_event,))
process.start()
- sleep(0)
+ # Wait until the child has installed its signal handlers, so that
SIGTERM will be
+ # ignored and we actually exercise the SIGKILL path. Without this, on
non-fork
+ # start methods (forkserver/spawn) the child may still have the
default SIGTERM
+ # handler when we send the signal.
+ ready_event.wait(timeout=10)
all_processes = subprocess.check_output(["ps", "-ax", "-o",
"pid="]).decode().splitlines()
assert str(process.pid) in (x.strip() for x in all_processes)