From 52a1c3dbc0d16c99620cd908fdda9df8f2c87a54 Mon Sep 17 00:00:00 2001 From: Aarthy Adityan Date: Fri, 15 May 2026 00:12:10 -0400 Subject: [PATCH 1/2] fix(standalone): revert Windows signal forwarding to TerminateProcess MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CTRL_BREAK_EVENT delivery is unreliable on Windows — the scheduler's threading.Event.wait doesn't wake on SIGBREAK from a different thread context, so the parent's children-watcher loop never empties and Ctrl+C hangs the whole tree. Reported by Chip; reproduced on the AWS WorkSpace. The orphan-postgres bug that motivated the CTRL_BREAK_EVENT switch is already addressed by the other half of fde7321 — children call ensure_standalone_setup() instead of get_server(), so they no longer register PIDs in pgserver's on-disk handle list. Force-killing them is safe; only the parent owns the pgserver handle and exits via the normal atexit path. Co-Authored-By: Claude Opus 4.7 (1M context) --- testgen/__main__.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/testgen/__main__.py b/testgen/__main__.py index 3b8d7f12..a1ea67a1 100644 --- a/testgen/__main__.py +++ b/testgen/__main__.py @@ -146,12 +146,16 @@ def _install_shutdown_handler(handler) -> None: def _forward_signal_to_child(child: subprocess.Popen, signum: int) -> None: - # POSIX: forward the signal verbatim. Windows: send CTRL_BREAK_EVENT so the - # child's atexit hooks run (it deregisters from pgserver's PID list, lets - # streamlit/uvicorn shut down their event loops, etc.). The child must have - # been spawned with CREATE_NEW_PROCESS_GROUP — see _subprocess_spawn_kwargs. + # POSIX: forward the signal verbatim. Windows: TerminateProcess — graceful + # CTRL_BREAK_EVENT delivery is unreliable here because some children + # (notably the scheduler thread blocked in threading.Event.wait, and + # Streamlit/tornado) don't wake on SIGBREAK, leaving the parent's + # children-watcher loop hung forever. Force-kill is safe: children no + # longer call pgserver.get_server(), so there's no on-disk PID registry + # state to clean up — only the parent owns the pgserver handle and + # exits via the normal atexit path. if sys.platform == "win32": - child.send_signal(signal.CTRL_BREAK_EVENT) + child.terminate() else: child.send_signal(signum) From 4297e6ff0cb1d78ef3a4f253f515c78089aef05e Mon Sep 17 00:00:00 2001 From: Aarthy Adityan Date: Fri, 15 May 2026 00:29:34 -0400 Subject: [PATCH 2/2] release: 5.33.2 -> 5.33.3 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 13924a31..b7d263a2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta" [project] name = "dataops-testgen" -version = "5.33.2" +version = "5.33.3" description = "DataKitchen's Data Quality DataOps TestGen" authors = [ { "name" = "DataKitchen, Inc.", "email" = "info@datakitchen.io" },