Check cancellation at the PTY execution boundary after executable sampling
and descriptor cleanup settle. Completed file observations cannot authorize
launch for a cancelled request. Preserve exact caller reasons in the shared
capture cancellation constructor and its admission, exit and finalization
consumers instead of reconstructing them downstream.
Exercise real executable reads and closes through the capture API with a
throwing PTY sentinel at five schedules. Retain a real completed Node capture
and its cleanup facts when the final progress callback cancels the request.
Strengthen existing metadata and baseline cancellation controls.
Adapted after review of #4836 at 014afa3892.
Raw snapshot/sampler descriptor cleanup ownership remains tracked in #5140;
this execution-admission change does not claim to solve failed close recovery.
Closes #4512
Closes #5142
Co-authored-by: DeryFerd <deryferdikao125@gmail.com>
24 lines
930 B
TypeScript
24 lines
930 B
TypeScript
import { open, stat, type FileHandle } from "node:fs/promises";
|
|
import { expect, it } from "vitest";
|
|
import { observeSelectedExecutable } from "../../../src/process/capture/ProcessCaptureLifecycle.js";
|
|
|
|
it("cancels after real metadata IO without creating an already-aborted stream or leaking the file handle", async () => {
|
|
const controller = new AbortController();
|
|
const reason = new Error("cancel after executable path metadata");
|
|
let opened: FileHandle | undefined;
|
|
await expect(
|
|
observeSelectedExecutable(process.execPath, controller.signal, {
|
|
async open(path, flags) {
|
|
opened = await open(path, flags);
|
|
return opened;
|
|
},
|
|
async stat(path) {
|
|
const metadata = await stat(path, { bigint: true });
|
|
controller.abort(reason);
|
|
return metadata;
|
|
},
|
|
}),
|
|
).rejects.toMatchObject({ reason: "cancelled", cause: reason });
|
|
expect(opened?.fd).toBe(-1);
|
|
});
|