opencode icon indicating copy to clipboard operation
opencode copied to clipboard

fix: resolve BashTool hanging on background commands

Open dnouri opened this issue 5 months ago • 0 comments

BashTool hung indefinitely on background commands (sleep 5 &, node server.js &) due to file descriptor inheritance. await process.exited blocked because background processes inherited stdout/stderr pipes from the parent bash shell.

  1. Bun.spawn() creates bash with stdout: "pipe", stderr: "pipe"
  2. Bash executes command & and exits
  3. Background process inherits pipe descriptors
  4. process.exited waits for all descriptors to close
  5. Background process keeps descriptors open → infinite hang

Added background command detection with selective I/O redirection:

const isBackground = isBackgroundCommand(params.command)
stdout: isBackground ? "ignore" : "pipe",
stderr: isBackground ? "ignore" : "pipe",

Background detection handles:

  • Simple: sleep 5 &
  • Complex: (cmd1; cmd2) &, nohup cmd &, cmd & disown
  • Edge cases: quoted strings, escaped ampersands
  • Mixed commands treated as foreground to preserve output

Now:

  • Background commands return quickly (vs infinite hang)
  • 35 comprehensive tests covering unit, integration, and edge cases
  • Full backward compatibility maintained
  • No performance impact on foreground commands

⚠️ One weakness here is that the new isBackgroundCommand function is 83 lines long and tries to handle a lot of cases. This might be a bit much for an issue that doesn't seem to occur for a lot of developers (haven't seen an open issue about this). At the same time, this PR might be a segway to fixing other issues with BashTool I/O as well such as #652 (App becomes unresponsive when executing commands requiring sudo password).

dnouri avatar Jul 23 '25 17:07 dnouri