Skip to content

Commit 73f4a43

Browse files
committed
test(windows): isolate the daemon guards' rendezvous and stop hiding their failures
Every Windows guard shared ONE daemon. test_daemon_stability.py said each section "runs under its OWN cache directory: daemon coordination is cache-scoped" -- it is not. The rendezvous key is FNV-1a over a compile-time domain string (service.c: cbm_daemon_rendezvous_key) under a machine-global parent (win_default_runtime_parent -> SHGetFolderPathW(CSIDL_LOCAL_APPDATA), which ignores the LOCALAPPDATA variable). So the guard's own `daemon stop` and kill -9 sections, the sibling guards, and anything else on the runner all met the same daemon, and a daemon wedged anywhere failed every check after it. That is the shape of this week's test-windows-guards red on DeusData#1874: lifecycle's `daemon start` connected, the UI-config handshake never answered, and stability / hook_augment / ui_drive / cli_non_ascii went red in a row with an orphan daemon killed at cleanup -- on a diff and a base that were each green elsewhere. CBM_RUNTIME_DIR is the only relocation hook (bootstrap.c, resolved in cbm_daemon_bootstrap_endpoint_new for every product endpoint). Each stability section now gets a private runtime parent next to its cache, created before the binary runs -- the endpoint validates the parent and never creates it -- and the daemon inherits it from the client that spawns it. Proven on macOS: a daemon on the default rendezvous keeps its pid across the whole guard (three stops and a kill -9 inside it). The reporting was hiding the cause as well: * every SETUP FAIL printed nothing at all, and every RED printed a 300-400 character HEAD slice, which is the allocator preamble, never the error. Excerpts now show the tail (1500 chars); setup paths print the daemon's full output. * a subprocess timeout raised on a parallel-client worker thread was lost and the client reported as "rc=none" with no output; it is now kept as a failed result with its partial output. A section-level timeout is a named RED with the command and output, not a bare traceback. * the MCP session's stderr went to DEVNULL; it now goes to a file that is printed when initialize never answers -- and that case is a RED against a running daemon, not a "setup" skip. * exit 2 was documented and never produced. Only `daemon start` failing raises it now (test_daemon_lifecycle.py owns that surface as a regression, so the board loses nothing); main() runs every section and names all of the failing ones. * test_hook_augment.py / test_cli_non_ascii_arg.py print full stdout AND stderr on their index-setup failures instead of 300 chars of stdout. On POSIX (local iteration only) the namespace lives under /tmp: sun_path caps the socket at 104 bytes on macOS and TMPDIR there is ~50 bytes deep. Out of scope, noted: test_daemon_lifecycle.py, test_non_ascii_path.py and test_ui_drive_listing.py still use the machine-global rendezvous; a too-long CBM_RUNTIME_DIR on POSIX is refused (ipc.c sun_path check) with no validation detail. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
1 parent bac8edc commit 73f4a43

3 files changed

Lines changed: 168 additions & 63 deletions

File tree

‎tests/windows/test_cli_non_ascii_arg.py‎

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ def main():
7373
# (#1952). One retry against a fresh cache separates that from a real
7474
# CLI indexing failure.
7575
ctrl_out = ""
76+
ctrl_err = ""
7677
for attempt in ("cache_ascii", "cache_ascii_retry"):
7778
env = dict(os.environ)
7879
env["CBM_CACHE_DIR"] = os.path.join(work, attempt)
@@ -81,14 +82,19 @@ def main():
8182
json.dumps({"repo_path": ascii_repo})],
8283
capture_output=True, timeout=120, env=env)
8384
ctrl_out = (ctrl.stdout or b"").decode("utf-8", "replace")
85+
ctrl_err = (ctrl.stderr or b"").decode("utf-8", "replace")
8486
if '"nodes"' in ctrl_out:
8587
break
86-
print("SETUP: ASCII control attempt %r did not index via CLI:\n%s"
87-
% (attempt, ctrl_out[:300]))
88+
# Full stdout AND stderr: the reason lives on stderr (daemon
89+
# spawn/handshake diagnostics), and a head slice of stdout only
90+
# ever showed the allocator preamble.
91+
print("SETUP: ASCII control attempt %r did not index via CLI (rc=%s):\n"
92+
"stdout:\n%s\nstderr:\n%s"
93+
% (attempt, ctrl.returncode, ctrl_out, ctrl_err))
8894
time.sleep(2)
8995
if '"nodes"' not in ctrl_out:
90-
print("SETUP FAIL: ASCII control did not index via CLI:\n%s" %
91-
ctrl_out[:300])
96+
print("SETUP FAIL: ASCII control did not index via CLI:\nstdout:\n%s\nstderr:\n%s"
97+
% (ctrl_out, ctrl_err))
9298
return 2
9399

94100
env2 = dict(os.environ)

0 commit comments

Comments
 (0)