Tear shells down off the event loop (destroy_session froze it) #2
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "teardown-off-loop"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
destroy_sessionfroze the whole event loop.It ran
sendintr()+cleanup()— signalling the shell and closing its pty — straight from the async handler. Closing a pty is synchronous end to end, so a heartbeat ticking every 10ms got zero ticks through for the entire teardown. On the shared server that freezes every other chat's tool call until the pty is gone. The same synchronous teardown runs whenbabash_initializeresets a knownchat_id(create_chatcleans up the old workspace before building the new one).Fix
close_shellrunssendintr()+cleanup()in a worker thread;create_chatis dispatched to a thread too.BashStateconstructor already defers the pty fork to its own thread, so only a process-table scan for orphaned babash screens runs on the caller (~18ms in isolation, but on every spawn, growing with process/screen count on a busy server).spawn_shellmoves that off the loop as well.Honest scoping
Two things I corrected while investigating:
forkptyDeprecationWarning is pre-existing, not introduced here. babash has always forked the pty insideBashState._init_thread, so the warning fires on a plain main-thread spawn too. It's inherent to spawning ptys in a threaded process; pexpect forks-then-execs, so the window is pexpect's to manage. Left untouched — suppressing a real warning would hide a real (if low, long-standing) signal.Guard
test_no_loop_blocking: the teardown assertion fails on the old code (zero heartbeats) and passes now. The spawn assertion is a looser smoke check — spawn never froze the loop outright, so it can't separate old from new as sharply, and the test says that rather than pretending otherwise.95 tests,
mypy --strictandruffclean.🤖 Generated with Claude Code