fix(agent-codex): reject pending requests before emitting error event
Move this.emit("error", err) after the pending-rejection loop in
handleProcessError, matching handleProcessExit's order. Without this,
emit("error") with no listeners throws synchronously, skipping
cleanup of pending requests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
89d2b5ead3
commit
3f81936467
|
|
@ -747,6 +747,28 @@ describe("CodexAppServerClient", () => {
|
|||
expect(client.isConnected).toBe(false);
|
||||
});
|
||||
|
||||
it("rejects pending requests before emitting error (no listener crash safe)", async () => {
|
||||
const proc = createFakeProcess();
|
||||
const client = new CodexAppServerClient({ requestTimeout: 5000 });
|
||||
|
||||
await connectClient(client, proc);
|
||||
|
||||
// Do NOT attach an error listener — emit("error") will throw
|
||||
// Start a request that will be pending
|
||||
const requestPromise = client.threadList();
|
||||
await new Promise((r) => setTimeout(r, 10));
|
||||
|
||||
// Process emits error — without a listener, emit("error") throws.
|
||||
// Pending requests must still be rejected before that throw.
|
||||
try {
|
||||
proc.emit("error", new Error("spawn ENOENT"));
|
||||
} catch {
|
||||
// Expected: uncaught error event from EventEmitter
|
||||
}
|
||||
|
||||
await expect(requestPromise).rejects.toThrow("spawn ENOENT");
|
||||
});
|
||||
|
||||
it("handles malformed JSON lines gracefully", async () => {
|
||||
const proc = createFakeProcess();
|
||||
const client = new CodexAppServerClient({ requestTimeout: 500 });
|
||||
|
|
|
|||
|
|
@ -494,13 +494,14 @@ export class CodexAppServerClient extends EventEmitter {
|
|||
this.readline = null;
|
||||
}
|
||||
|
||||
this.emit("error", err);
|
||||
|
||||
// Reject all pending requests
|
||||
// Reject all pending requests before emitting "error" — emit("error")
|
||||
// with no listeners throws synchronously, which would skip cleanup.
|
||||
for (const [id, pending] of this.pending) {
|
||||
clearTimeout(pending.timer);
|
||||
pending.reject(err);
|
||||
this.pending.delete(id);
|
||||
}
|
||||
|
||||
this.emit("error", err);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue