Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

node:child_process#spawn doesn't fire close event if app exits immediately after spawned app exits #3083

Closed
vjpr opened this issue May 26, 2023 · 3 comments · Fixed by #5481
Assignees
Labels
bug Something isn't working node.js Compatibility with Node.js APIs

Comments

@vjpr
Copy link
Contributor

vjpr commented May 26, 2023

What version of Bun is running?

0.6.3

What platform is your computer?

Darwin 22.2.0 arm64 arm

What steps can reproduce the bug?

Try the example from here: https://nodejs.org/api/child_process.html#event-close

const { spawn } = require('node:child_process');
const ls = spawn('ls', ['-lh', '/usr']);

ls.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

ls.on('close', (code) => {
  console.log(`child process close all stdio with code ${code}`);
});

ls.on('exit', (code) => {
  console.log(`child process exited with code ${code}`);
}); 

brew install watchman
import {spawn} from 'node:child_process'
import Bun from 'bun'

export default async function index() {
  console.log('Bun Child Process')

  //const watchmanBin = Bun.which('watchman')
  const watchmanBin = '/opt/homebrew/bin/watchman'

  const args = ['version']
  const spawnOpts = {
    stdio: ['pipe', 'pipe', 'pipe'],
  }
  const child = spawn(watchmanBin, args, spawnOpts)
  child.stdout.on('data', data => {
    data = data.toString('utf8')
    console.log(data)
  })
  child.stderr.on('data', data => {
    console.log(data)
  })
  child.on('close', (code, signal) => {
    console.log('closed')
    console.log({code, signal})
  })

  return 1
}

What is the expected behavior?

Node.js

Bun Child Process
{
    "version": "2023.05.15.00"
}

closed
{ code: 0, signal: null }

What do you see instead?

Bun

Bun Child Process
{
    "version": "2023.05.15.00"
}


Additional information

This prevents fb-watchman package from working.

@vjpr vjpr added the bug Something isn't working label May 26, 2023
@vjpr
Copy link
Contributor Author

vjpr commented May 26, 2023

(exitCode, signalCode, err) => this.#handleOnExit(exitCode, signalCode, err),

calls:

this.emit("exit", this.exitCode, this.signalCode);

Only exit is being fired...but even that is not working.


I check with this underlying impl, and the issue is process.nextTick is not firing...

this.#handle = Bun.spawn({
cmd: spawnargs,
stdin: bunStdio[0],
stdout: bunStdio[1],
stderr: bunStdio[2],
cwd: options.cwd || undefined,
env: env || process.env,
onExit: (handle, exitCode, signalCode, err) => {
this.#handle = handle;
this.pid = this.#handle.pid;
process.nextTick(
(exitCode, signalCode, err) => this.#handleOnExit(exitCode, signalCode, err),
exitCode,
signalCode,
err,
);
},
lazy: true,
});

@vjpr
Copy link
Contributor Author

vjpr commented May 26, 2023

When I add setInterval(() => {}, 100) at the bottom of my program, it prints fine.

So the issue seems to be that the program exits before the nextTick in the onExit cb can fire.

@vjpr vjpr changed the title node:child_process#spawn doesn't fire close event node:child_process#spawn doesn't fire close event if app exits immediately after spawned app exits May 26, 2023
@Electroid Electroid added the node.js Compatibility with Node.js APIs label May 27, 2023
@Hanaasagi
Copy link
Collaborator

The issue still persists in 1.0.1

const { spawn } = require("node:child_process");

function exitHandler(code, signal) {
  console.log(code, signal);
}

const p = spawn("ls", ["-l"]);

p.on("exit", exitHandler);
p.on("close", exitHandler);

both close and exit is not emitted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working node.js Compatibility with Node.js APIs
Projects
None yet
4 participants