From 6ddde9376ced68968738bf4e58d2dceaf5a31c10 Mon Sep 17 00:00:00 2001 From: catborise Date: Wed, 21 Oct 2026 12:05:55 +0300 Subject: [PATCH] test(operations): a worker a process test cannot stop shows where it is stuck CI once found a test worker still running 15 s after SIGTERM, and the failure said nothing more. The worker children now dump their threads' stacks on SIGUSR1, and tearDown sends it to a child that is still alive before killing it, so the next such failure names the place. Co-Authored-By: Claude Opus 5.5 (1M context) --- operations/tests/test_processes.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/operations/tests/test_processes.py b/operations/tests/test_processes.py index c9587c8b..fa3eb5c7 100644 --- a/operations/tests/test_processes.py +++ b/operations/tests/test_processes.py @@ -1,6 +1,7 @@ """Real processes: a worker killed at each point is recovered by the next; one worker per host; concurrent admissions and submissions never double up.""" +import faulthandler import multiprocessing import os import shutil @@ -19,6 +20,7 @@ from operations.tests import fakes, proc_kinds # noqa: F401 def _worker(data): connections.close_all() + faulthandler.register(signal.SIGUSR1, all_threads=True) # tearDown asks a stuck worker where it is from operations.worker import Worker os._exit(Worker(tick=0.05, heartbeat_every=0.2, grace=1, data=data).run()) @@ -60,6 +62,8 @@ class ProcessTestCase(TransactionTestCase): def tearDown(self): for p in self.children: if p.is_alive(): + os.kill(p.pid, signal.SIGUSR1) # its threads' stacks go to stderr + p.join(1) p.kill() p.join(10) shutil.rmtree(self.dir, ignore_errors=True)