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

Exit Code 137 when a background subprocess is closed externally #11055

Closed
wellwelwel opened this issue May 13, 2024 · 3 comments
Closed

Exit Code 137 when a background subprocess is closed externally #11055

wellwelwel opened this issue May 13, 2024 · 3 comments
Labels
bug Something isn't working

Comments

@wellwelwel
Copy link

wellwelwel commented May 13, 2024

What version of Bun is running?

1.1.8+89d25807f


What platform is your computer?

Darwin 23.4.0 arm64 arm


What steps can reproduce the bug?

When a subprocess is started, but is terminated externally (e.g., using kill -9), Bun executes the entire script normally until its end, but terminates the process with code 137 if this subprocess was previously called (using fetch, for example), even if it all worked properly.

I've created a minimal repository for a simple step-by-step repro using solely native Bun features:
https://github.com/wellwelwel/bun-unexpected-exit-code-137

Steps

  • Start a subprocess (e.g., spawn) that will be used in background
  • Fetch it
  • Close the subprocess directly by PID
  • Wait for the main process to be completed

If "fetch" step is removed, everything will work perfectly.

lib/server.ts
// Nothing wrong here (it could be any service or server, using Bun or not) 🙋🏻‍♂️

Bun.serve({
  port: 4000,
  fetch: () => new Response('✅ Server is Live'),
});
lib/pid.ts
// Nothing wrong here (just for context) 🙋🏻‍♂️

const findPID = (port: number): Promise<number[]> =>
  new Promise(async (resolve) => {
    const PIDs: Set<number> = new Set();
    const service = Bun.spawn(['lsof', '-t', '-i', `:${Number(port)}`]);

    const output = (await new Response(service.stdout).text())
      .trim()
      .split('\n');

    output.forEach((pid) => {
      if (pid) PIDs.add(Number(pid));
    });

    return resolve(Array.from(PIDs));
  });

const killPID = async (PID: number) => {
  const proc = Bun.spawn(['kill', '-9', PID.toString()]);

  return await proc.exited;
};

export const killPort = async (port: number) => {
  const PIDs = await findPID(port);

  PIDs.forEach(async (PID) => await killPID(PID));
};
repro.error.ts
import { killPort } from './lib/pid.js';

// Start the server in background
try {
  const proc = Bun.spawn(['bun', 'lib/server.ts'], {
    // It doesn't run if "fetch" is used
    onExit: (proc) => {
      console.log('✅ Sub process signal Code is', proc.signalCode);
      console.log('✅ Sub process exit code is', proc.exitCode);
    },
  });

  const error = await new Response(proc.stderr).text();
  if (error) console.log(error);
} catch (quiet) {
}

const repro = async () => {
  const res = await (await fetch('http://localhost:4000')).text();
  console.log(res);

  await killPort(4000);

  console.log('✅ Module continues to work normally after closing the PIDs');
};

setTimeout(repro, 1000);

// It doesn't run if "fetch" is used
process.on('exit', (code) => {
  console.log('✅ Exit Code is', code);
});

Output

bun repro.error.ts
✅ Server is Live
✅ Module continues to work normally after closing the PIDs
[1]    7901 killed     bun repro.error.ts

ℹ️ Note that the error is not exactly related to fetch itself. Even using node:http or an external package, the issue seems to be related to the simple fact of Bun triggers a service running in the background.

Testing manually, this behavior also occurred on Linux, including the official Docker Alpine images to check different Bun versions and the platform linux/amd64.


What is the expected behavior?

I tried the same approach for Deno and Node.js, and everything worked normally in all cases, as expected.

Also, in Bun, by just not calling the background subprocess, everything will work as usual:

repro.success.ts
import { killPort } from './lib/pid.js';

try {
  const proc = Bun.spawn(['bun', 'lib/server.ts'], {
    // Without "fetch", everything works fine
    onExit: (proc) => {
      console.log('✅ Sub process signal Code is', proc.signalCode);
      console.log('✅ Sub process exit code is', proc.exitCode);
    },
  });

  const error = await new Response(proc.stderr).text();
  if (error) console.log(error);
} catch (quiet) {
}

const repro = async () => {
  // const res = await (await fetch('http://localhost:4000')).text();
  // console.log(res);

  await killPort(4000);

  console.log('✅ Module continues to work normally after closing the PIDs');
};

setTimeout(repro, 1000);

// Without "fetch", everything works fine
process.on('exit', (code) => {
  console.log('✅ Exit Code is', code);
});
  • Same code, just commenting fetch

Output

bun repro.success.ts
✅ Module continues to work normally after closing the PIDs
✅ Sub process signal Code is SIGKILL
✅ Sub process exit code is null
✅ Exit Code is 0

What do you see instead?

A visual output of both the error and success examples:

Screenshot 2024-05-13 at 18 55 24 Screenshot 2024-05-13 at 19 03 00

Additional information

I noticed that both Bun and Deno reproduce the issue #7441. To solve this in my package, I've allowed the user to pass a port when finishing a subprocess to ensure its end.

But even if the process terminates completely successfully, this happens (due to the 137 exit code — this reported issue):

The following test results use node:child_process and node:http, so this issue also occurs by using solely native Node.js features and using Bun just to run it (although it works normally for Node.js and Deno).

Screenshot 2024-05-13 at 19 37 03

Thanks for your time 🙋🏻‍♂️

@wellwelwel wellwelwel added the bug Something isn't working label May 13, 2024
@wellwelwel wellwelwel changed the title Exit Code 137 when background subprocess is closed externally Exit Code 137 when background a subprocess is closed externally May 14, 2024
@wellwelwel wellwelwel changed the title Exit Code 137 when background a subprocess is closed externally Exit Code 137 when a background subprocess is closed externally May 14, 2024
@paperdave paperdave removed the bug Something isn't working label May 15, 2024
@robobun robobun added question Further information is requested typescript Something for TypeScript transpiler parser || printer tracking An umbrella issue for tracking big features node.js Compatibility with Node.js APIs needs repro Needs an example to reproduce performance An issue with performance needs tests Something that needs more testing napi Compatibility with the native layer of Node.js crash An issue that could cause a crash web-api Something that relates to a standard Web API npm Something that relates to the npm-compatible client os Something wrong with a specific OS sqlite Something to do with bun:sqlite wasm Something that related to WASM or WASI support tech debt proposal regression debugger Something to do with `bun --inspect` or the debugger vscode Something to do with the VSCode extension windows An issue that only occurs on Windows macOS An issue that only occurs on macOS linux An issue that only occurs on Linux cli Something to do with CLI arguments repl An issue with `bun repl` labels May 15, 2024
@paperdave paperdave added bug Something isn't working and removed npm Something that relates to the npm-compatible client os Something wrong with a specific OS sqlite Something to do with bun:sqlite wasm Something that related to WASM or WASI support tech debt proposal regression debugger Something to do with `bun --inspect` or the debugger vscode Something to do with the VSCode extension windows An issue that only occurs on Windows macOS An issue that only occurs on macOS linux An issue that only occurs on Linux cli Something to do with CLI arguments repl An issue with `bun repl` atw docker An issue that occurs when running in Docker lambda An issue related to the AWS Lambda layer ffi Something related with FFI in Bun needs investigate Needs to be investigated to find the root cause idea quick fix Something that can be fixed with low effort, but high impact shell Something to do with Bun as a shell types An issue with TypeScript types cjs duplicate glob Related to Bun.Glob sourcemaps breaking labels May 15, 2024
@wellwelwel
Copy link
Author

wellwelwel commented May 15, 2024

Thanks, @paperdave 🤝

Same approach worked for Windows, using netstat instead.

Screenshot 2024-05-15 at 03 05 21

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants