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)

Reply via email to