aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
authorblasty <blasty@local>2026-07-09 11:55:43 +0200
committerblasty <blasty@local>2026-07-09 11:55:43 +0200
commit21d2cbbfcdbb712b907573b784bc9d98d5c5e648 (patch)
tree8d2c94975c30e13501f0c8c8785230cae235ae98 /docs
parentdomain/paging layer: FunctionIndex, block-cached DisasmModel, decompile, resolve (diff)
downloadida-tui-21d2cbbfcdbb712b907573b784bc9d98d5c5e648.tar.gz
ida-tui-21d2cbbfcdbb712b907573b784bc9d98d5c5e648.tar.xz
ida-tui-21d2cbbfcdbb712b907573b784bc9d98d5c5e648.zip
keep idle workers alive: bump_idle_ttl + KeepAlive heartbeat
Root cause: idalib workers run an idle watchdog (worker_lifecycle.py) that self-exits after idle_ttl_sec (default 600s) of no requests -- deliberate resource hygiene for a shared/ephemeral supervisor, wrong for an interactive TUI. CLI-opened startup binary always gets 600s (no flag). Fix (both verified against a 12s-TTL session): - IDAClient.bump_idle_ttl(1e9): re-open (idempotent) re-applies TTL, no upper cap -> effectively immortal. Primary fix, call once at startup. - IDAClient.keepalive()/KeepAlive: background server_health heartbeat resets the watchdog; covers adopted sessions too. Safety net. tests/test_keepalive.py: 4/4 (heartbeat + bump both keep a short-TTL worker alive past 2x TTL). docs updated with why + fix.
Diffstat (limited to 'docs')
-rw-r--r--docs/PAGING_FINDINGS.md37
1 files changed, 29 insertions, 8 deletions
diff --git a/docs/PAGING_FINDINGS.md b/docs/PAGING_FINDINGS.md
index 33cb2e6..3d3ec1a 100644
--- a/docs/PAGING_FINDINGS.md
+++ b/docs/PAGING_FINDINGS.md
@@ -93,15 +93,36 @@ fall back to the disassembly view or show an error panel.
Normal decompile bodies are server-truncated with a `[N chars total]` marker
(still to be solved for full-body display — see Phase 2).
-## Workers self-exit when idle (`idle_ttl_sec`, default 600s)
+## Workers self-exit when idle (`idle_ttl_sec`, default 600s) — SOLVED
-A headless idalib worker self-exits after ~10 min idle. Its session then lingers
-in `idb_list` but calls fail with `"Worker for session <id> is not reachable"`
-(distinct from `"Session not found"`). Recovery differs: this needs a fresh
-`idb_open` of the same `input_path` (new worker), not just a db re-resolve. The
-TUI should (a) raise `idle_ttl_sec` when opening, and/or (b) detect
-"not reachable" and transparently re-open. Currently surfaced as a clean
-`IDAToolError`; auto-reopen is a TODO for the app layer.
+### Why it happens
+Each idalib worker runs a `WorkerLifecycle` watchdog
+(`ida_pro_mcp/worker_lifecycle.py`): if no JSON-RPC request hits its dispatcher
+for `idle_ttl_sec` (default **600s**), the worker **self-exits cleanly**. It is
+refcount-free — "activity == alive": every forwarded tool call `touch()`es the
+timer. This is deliberate resource hygiene for a *shared* supervisor (each worker
+holds an IDA license slot + the DB's RAM; default max 4 workers), aimed at
+ephemeral/agent usage that opens a DB and wanders off. For an **interactive TUI
+that should be able to just chill, it's the wrong default.** The startup binary
+passed to `idalib-mcp` on the CLI always gets 600s (no CLI flag to change it).
+
+After self-exit the session lingers in `idb_list` but calls fail with
+`"Worker for session <id> is not reachable"` (distinct from `"Session not
+found"`).
+
+### The fix (both implemented + verified in `tests/test_keepalive.py`)
+1. **`IDAClient.bump_idle_ttl(idle_ttl_sec=1e9)`** — `idb_open` on the
+ already-open path is idempotent and re-applies the TTL; `set_idle_ttl` has no
+ upper cap, so ~1e9s is effectively 'never'. This is the intended knob and the
+ primary fix: the TUI calls it once at startup.
+2. **`IDAClient.keepalive(interval=120)` -> `KeepAlive`** — a background
+ heartbeat issuing a cheap `server_health` (~2ms) that resets the watchdog.
+ Belt-and-suspenders, and it also covers *adopted* sessions whose path we don't
+ control / don't want to re-open.
+
+Recommended TUI policy: `bump_idle_ttl()` on open **and** run a `KeepAlive` as a
+safety net. "Worker not reachable" then only occurs on a real crash, which the
+app handles by re-`idb_open`.
## Writable path requirement (operational)