<feed xmlns='http://www.w3.org/2005/Atom'>
<title>ida-tui.git/tests/test_worker_client.py, branch pre-codemode</title>
<subtitle>tui for headless ida</subtitle>
<id>https://git.sl0p.foo/ida-tui.git/atom/tests/test_worker_client.py?h=pre-codemode</id>
<link rel='self' href='https://git.sl0p.foo/ida-tui.git/atom/tests/test_worker_client.py?h=pre-codemode'/>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/ida-tui.git/'/>
<updated>2026-08-06T22:14:28Z</updated>
<entry>
<title>worker_client: tests, and stop resurrecting a closed worker</title>
<updated>2026-08-06T22:14:28Z</updated>
<author>
<name>blasty</name>
<email>blasty@local</email>
</author>
<published>2026-08-06T22:14:28Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/ida-tui.git/commit/?id=89db0e023d5bafbd1868f22b9b31e5006066cdad'/>
<id>urn:sha1:89db0e023d5bafbd1868f22b9b31e5006066cdad</id>
<content type='text'>
The layer between the app and idalib had no tests, which is awkward: it is
where failures are silent. A worker that dies during startup, a socket that
drops mid-call, two UI threads sharing one socket -- none of those look like
bugs from outside, they look like the TUI hanging or showing stale data.

None of it needs IDA. WorkerClient spawns whatever _WORKER_PY points at, so the
suite points it at a fake speaking the same length-prefixed pickle and tells it
to misbehave on demand: die at startup, never bind, drop the connection, fail a
tool, take its time. 40 checks in the --fast tier.

Two things the tests found:

call() reconnects when _sock is None, which is what makes a dropped socket
recoverable -- but it made an explicitly CLOSED client resurrect too, spawning a
whole new idalib worker to serve one stray call (verified: pid 1066961 -&gt;
1066962). close() runs on teardown and on binary-switch while @work threads are
still in flight, so quitting during a decompile could leave a fresh process
re-opening the .i64 we had just released, which is the wedging hazard. A closed
client now refuses; connect() still revives it, which is all _reconnect needs
(it builds a new client anyway).

connect() polled on a flat 0.2s sleep, so every caller paid a fifth of a second
even when the worker was ready in milliseconds -- a seeded .i64, a small binary.
Backs off from 5ms instead.

786 checks, 144.6s; --fast is 297 in 3.3s.
</content>
</entry>
</feed>
