Problem
The current shared runtime can release its lifetime lock while a resident LSP process or descendant is still alive.
LeanLspSession._abort_process() clears self.process before cleanup, kills only the wrapper process, and suppresses every kill() / wait() failure. close() then returns success. ProjectResourceCache consequently retires the session as clean even though ownership may have been lost.
This was reproduced during the adversarial review of closed #101 with a process whose cleanup fails: the handle is discarded and the fake process remains alive. A real wrapper-exits-first case also leaves its child outside the current parent-only cleanup path.
Required behavior
- launch the LSP wrapper in a dedicated process group;
- retain the process handle and process-group id until group exit and parent reaping are verified;
- make failed cleanup observable so the project cache quarantines and retries it;
- mark a poisoned session invalid before abort cleanup, so a cleanup exception cannot make the broken protocol stream reusable;
- preserve ownership across initialization failure as well as normal close/abort;
- test stubborn cleanup, surviving descendants, retry, and runtime stop/replacement serialization.
This was intentionally kept out of the minimal #105–#107 REPL stack. It remains relevant until the LSP side of the Lean Beam migration in #41 replaces this backend.
Problem
The current shared runtime can release its lifetime lock while a resident LSP process or descendant is still alive.
LeanLspSession._abort_process()clearsself.processbefore cleanup, kills only the wrapper process, and suppresses everykill()/wait()failure.close()then returns success.ProjectResourceCacheconsequently retires the session as clean even though ownership may have been lost.This was reproduced during the adversarial review of closed #101 with a process whose cleanup fails: the handle is discarded and the fake process remains alive. A real wrapper-exits-first case also leaves its child outside the current parent-only cleanup path.
Required behavior
This was intentionally kept out of the minimal #105–#107 REPL stack. It remains relevant until the LSP side of the Lean Beam migration in #41 replaces this backend.