Skip to content

MessageChannel between Workers causes crash/unexpected exit #25805

@xentobias

Description

@xentobias

What version of Bun is running?

1.3.5+1e86cebd7

What platform is your computer?

Microsoft Windows NT 10.0.26200.0 x64 (Also reproduced on Linux x64)

What steps can reproduce the bug?

Create two workers and establish a MessageChannel between them by transferring ports.

src/index.ts:

import { Worker } from "worker_threads";

const worker1 = new Worker(new URL('./worker.ts', import.meta.url), {
  env: { WORKER_NAME: 'Worker 1' },
});

const worker2 = new Worker(new URL('./worker.ts', import.meta.url), {
  env: { WORKER_NAME: 'Worker 2' },
});

const ready = [worker1, worker2].map((worker) => {
  return new Promise((resolve) => {
    worker.addListener('message', (message) => {
      if (message === 'READY') {
        resolve(true);
      }
    });
  });
})

// Transfer the ports to the workers
const { port1, port2 } = new MessageChannel();
worker1.postMessage(port1, [port1] );
worker2.postMessage(port2, [port2] );

// Make sure both workers are ready before continuing
await Promise.all(ready);
console.log('All workers are ready');

// Option 1: Using setInterval - causes unexpected exit after ~30 seconds
// setInterval(() => {
//   worker1.postMessage('SEND_MESSAGE');
//   worker2.postMessage('SEND_MESSAGE');
// }, 50);

// Option 2: Using while loop - causes immediate segmentation fault
// while (true) {
//   worker1.postMessage('SEND_MESSAGE');
//   worker2.postMessage('SEND_MESSAGE');
// }

src/worker.ts:

import { parentPort } from "worker_threads";

const name = process.env.WORKER_NAME;
console.log("Worker name:", name);

let port: MessagePort | null = null;
parentPort?.addEventListener("message", (event) => {
  if (event.data instanceof MessagePort) {
    event.data.start();
    event.data.addEventListener("message", (event) => {
      console.log(`[${name}] Message from port:`, event.data);
    });

    port = event.data;
    console.log(`[${name}] Message port started and listening for messages`);
    parentPort?.postMessage('READY')
    return
  }

  if (event.data === 'SEND_MESSAGE') {
    port?.postMessage(`Hello from ${name}`);
    return
  }
});

Run with: bun run src/index.ts

What is the expected behavior?

The workers should be able to communicate with each other through the MessageChannel indefinitely without crashing.

What do you see instead?

Two different failure modes depending on how messages are sent:

Scenario 1: Using setInterval (every 50ms)

The process exits unexpectedly after approximately 30 seconds with no error output.

  • Exit code on Windows: -1073740791 ($LASTEXITCODE)

Scenario 2: Using while (true) loop

Immediate segmentation fault:

panic(thread 51916): Segmentation fault at address 0x8
oh no: Bun has crashed. This indicates a bug in Bun, not your code.

To send a redacted crash report to Bun's team,
please file a GitHub issue using the link below:

https://bun.report/1.3.5/wr11e86cebgWgghgCgvuhwDg5v+xD87v+xDyqv+xDsnv+xDqrthwDiysvnDsp0v7Bij0l8Bgqvl8B___A2AQ

Additional information

  • The bug reproduces on both Windows x64 and Linux x64.
  • The crash appears to be related to MessageChannel port transfer between workers.
  • The code executes smoothly in a Node.js environment.

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