From 1caedbbbc7f526df55f7ff4d924cfa06e31ab788 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 17 May 2026 02:14:29 +0000 Subject: [PATCH] bisect: kill-switch every audit-log write MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported: bisection commit c0bfd4d that disabled the sticky footer, diagnostics sidebar, and compact-CSS didn't fix the blank-page symptom. User adds that Ctrl+C also can't kill the launcher. Ctrl+C-doesn't-work + every-page-blank together points at a hang in the Python process, not an exception. The most likely hang point in the chrome path is the audit log's file I/O — ``open()`` inside the ``with`` block in ``log_event`` blocks on a stuck filesystem (Windows antivirus quarantining ``~/.datatools/logs/datatools-*.jsonl`` on every write is a plausible culprit on the user's machine). A blocking ``open`` call does NOT raise — try/except can't recover from it — which is why our prior defensive wrap didn't help. Add a module-level ``_DISABLED = True`` kill switch. ``log_event``, ``log_session_start``, and ``log_page_open`` each early-return at the very top of the function when the flag is set, before any file-system call. Path resolution (``audit_log_path``) still works since it's needed for the diagnostics sidebar (still disabled in c0bfd4d, but kept harmless). If pages render after this commit, file I/O from the audit log is confirmed as the culprit; we'll redesign with an async writer queue and a tighter timeout. If they still don't, the cause is somewhere we haven't bisected yet and we move to a hard revert. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/audit.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/audit.py b/src/audit.py index c0ecb61..c13cd22 100644 --- a/src/audit.py +++ b/src/audit.py @@ -57,6 +57,15 @@ _LOG_PATH: Path | None = None _SESSION_ID: str | None = None _SESSION_STARTED: bool = False +# Kill switch — when True, every log_* function is a no-op. Set to +# True while bisecting a "blank pages" report where ``open()`` inside +# the log writer was suspected of blocking on the user's filesystem +# (Windows + antivirus + ``~/.datatools/logs/``). A blocking ``open`` +# call doesn't raise so try/except can't recover it; the only safe +# bisect is "don't touch the disk at all." Toggle back to False once +# the user confirms pages render. +_DISABLED: bool = True + def audit_log_dir() -> Path: """Return the directory where audit logs are written. @@ -147,6 +156,8 @@ def log_event( Failures are swallowed silently — a broken audit log must not take the GUI down. """ + if _DISABLED: + return try: event = { "ts": datetime.now(tz=timezone.utc).isoformat(timespec="milliseconds"), @@ -172,6 +183,8 @@ def log_event( def log_session_start() -> None: """Write the session-start banner. Idempotent within one process.""" + if _DISABLED: + return global _SESSION_STARTED with _LOCK: if _SESSION_STARTED: @@ -222,6 +235,8 @@ def log_page_open(slug: str) -> None: Whole body is wrapped in try/except — the audit log is best- effort and MUST NOT crash the page that called it. """ + if _DISABLED: + return try: try: import streamlit as st