fix(lsp): address codex review round 2
Further lifecycle/safety hardening of the local provider: - Tear the instance down when the initialize handshake is aborted, so a poisoned pending `ready` can't make later queries for that workspace re-wait. - Make the serialized-queue wait itself abortable, so a query blocked behind hung earlier work can still observe its own timeout. - Spawn the server detached and signal the whole process group on teardown, so helper processes (e.g. tsserver) can't outlive dispose(). - Open the source with O_NOFOLLOW and cap the read at maxDocumentBytes+1, closing the symlink-swap and concurrent-grow windows the fd-based read left open. - Honor an already-aborted signal before any host I/O or startup. - Validate maxStderrBytes positive at load; surface the retained stderr tail in the "language server exited" error so a fatal startup diagnostic is visible.
This commit is contained in:
@@ -151,6 +151,25 @@ describe('lsp-local end to end over a fake server', () => {
|
||||
await ctx.fiber.dispose()
|
||||
})
|
||||
|
||||
it('honors an already-aborted signal before any host I/O or startup', async () => {
|
||||
const ctx = await mount({ LSP_FAKE_DEF: 'null' })
|
||||
const controller = new AbortController()
|
||||
controller.abort(new Error('pre-aborted'))
|
||||
await expect(ctx.lsp.query(query('definition'), controller.signal)).rejects.toThrow(/pre-aborted/)
|
||||
await ctx.fiber.dispose()
|
||||
})
|
||||
|
||||
it('surfaces the server stderr tail in the exit error', async () => {
|
||||
// A server that writes to stderr then exits without answering: the query rejection carries the
|
||||
// retained stderr tail so the failure is diagnosable.
|
||||
const ctx = await mount({}, {
|
||||
command: process.execPath,
|
||||
args: ['-e', 'process.stderr.write("FATAL: boom\\n"); setTimeout(()=>process.exit(1), 50)'],
|
||||
})
|
||||
await expect(ctx.lsp.query(query('definition'))).rejects.toThrow(/FATAL: boom/)
|
||||
await ctx.fiber.dispose()
|
||||
})
|
||||
|
||||
it('classifies a timeout deadline as the abort reason', async () => {
|
||||
const ctx = await mount({ LSP_FAKE_HANG: '1' })
|
||||
using d = deadline(undefined, 50, 'TEST_TIMEOUT')
|
||||
|
||||
Reference in New Issue
Block a user