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 014afa38929d46d58067b617c707759cd753cf8d. 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);
|
|
});
|