Skip to content

deno test --preload hangs when preload script spawns a child process with stdio: "pipe" #32122

@ben-melo

Description

@ben-melo

Version: Deno 2.6.9

Sumary

When a --preload script spawns a child process via node:child_process with stdio: "pipe", the test runner hangs indefinitely after the preload completes, even if unref() is called on the child process. Tests never start.

Environment

  • Deno 2.6.9
  • macOS 26.2

Minimal Reproduction

preload.ts

import { spawn } from "node:child_process";

// Any long-running process works — using "cat" for simplicity
const child = spawn("cat", [], { stdio: "pipe" });

child.stdout?.on("data", () => {});
child.stderr?.on("data", () => {});
child.unref(); // Should allow the event loop to proceed, not hang the preload

console.log("preload done");

test.ts

Deno.test("should run", () => {
  console.log("test executed");
});

Run

deno test --allow-all --preload=preload.ts test.ts

Actual behavior

------- pre-test output -------
preload done

Hangs here forever. Tests never execute.

Expected behavior

------- pre-test output -------
preload done
----- pre-test output end -----
running 1 test from test.ts
should run ... ok (0ms)

ok | 1 passed | 0 failed

Workaround

Manually destroy the stdio streams after they are no longer needed:

const child = spawn("some-process", [], { stdio: "pipe" });

// ... wait for the child to be ready ...

// Release the streams so deno test --preload can proceed
child.stdout?.removeAllListeners();
child.stdout?.destroy();
child.stderr?.removeAllListeners();
child.stderr?.destroy();

Real-World Impact

This affects any --preload script that starts a background service via node:child_process, such as:

  • mongodb-memory-server (spawns mongod with stdio: "pipe")
  • Any database/service helper that starts a process and keeps it running for the test suite

More

I would say that the bug is related to this line:

self.worker.run_event_loop(false).await?;

Because the stdio pipe handle will be alive and the run_event_loop will continue waiting, until the pending_ops is empty.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions