|
|
@@ -97,17 +97,20 @@ function replaceEnvironment(env: Record<string, string>): void {
|
|
|
Object.assign(process.env, env)
|
|
|
}
|
|
|
|
|
|
+interface MaterializedStdioStream {
|
|
|
+ readonly _handle?: { close(): void } | null
|
|
|
+}
|
|
|
+
|
|
|
+function closeMaterializedStdio(stream: NodeJS.WriteStream): void {
|
|
|
+ (stream as unknown as MaterializedStdioStream)._handle?.close()
|
|
|
+}
|
|
|
+
|
|
|
/** Release the runner's copies after the Windows target inherits its standard handles. */
|
|
|
function releaseRunnerStdio(): void {
|
|
|
const stdin = process.stdin
|
|
|
const stdout = process.stdout
|
|
|
const stderr = process.stderr
|
|
|
- // A loader may already have materialized Node's libuv stdio wrappers. Their
|
|
|
- // shutdown must be requested before the CRT descriptors close; the target
|
|
|
- // keeps the handles CreateProcessW inherited and remains the only pipe writer.
|
|
|
stdin.destroy()
|
|
|
- stdout.end()
|
|
|
- stderr.end()
|
|
|
for (const fd of [0, 1, 2]) {
|
|
|
try {
|
|
|
closeSync(fd)
|
|
|
@@ -115,6 +118,11 @@ function releaseRunnerStdio(): void {
|
|
|
if ((error as NodeJS.ErrnoException).code !== 'EBADF') throw error
|
|
|
}
|
|
|
}
|
|
|
+ // Node deliberately keeps stdout/stderr alive when destroy() is called. A
|
|
|
+ // loader may already have materialized their libuv handles, so close those
|
|
|
+ // runner-owned references explicitly; the target keeps its inherited copies.
|
|
|
+ closeMaterializedStdio(stdout)
|
|
|
+ closeMaterializedStdio(stderr)
|
|
|
}
|
|
|
|
|
|
async function runWin32(request: RunnerRequest, eventsPath: string): Promise<void> {
|