Skip to content

fix: prevent pkill hang when close event never firesFix/pkill hang#25672

Open
zenoda wants to merge 9 commits intoanomalyco:devfrom
zenoda:fix/pkill-hang
Open

fix: prevent pkill hang when close event never firesFix/pkill hang#25672
zenoda wants to merge 9 commits intoanomalyco:devfrom
zenoda:fix/pkill-hang

Conversation

@zenoda
Copy link
Copy Markdown

@zenoda zenoda commented May 4, 2026

Issue for this PR

Closes #25664

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Summary

  • Resolve exit-signal Deferred on exit event instead of close to prevent hang when pkill -f orphans children holding pipe FDs
  • Remove Deferred.await from SIGKILL escalation path since kill(SIGKILL) is synchronous on Linux
  • Add Effect.catch to exitCode in bash tool to prevent Effect.raceAll hang on Error

Changes

  • packages/core/src/cross-spawn-spawner.ts — two commits fixing Deferred resolution and SIGKILL escalation
  • packages/opencode/src/tool/bash.ts — catch exitCode Error in race

How did you verify your code works?

  • Open opencode TUI.
  • Send the message:
    • Execute:pkill -f vim 2>/dev/null; echo "killed"
      Observe that the tool call dose not hangs any more.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

chengda added 3 commits May 2, 2026 19:31
…r fires

The orElse path in Effect.timeoutOrElse (used for forceKillAfter escalation
from SIGTERM to SIGKILL) was awaiting the exit Deferred after sending SIGKILL.
If the Node.js close event never fires (e.g., orphaned children from pkill
holding pipe FDs), this Deferred.await hangs indefinitely with no timeout
protection — even after SIGKILL reaches the process.

Remove the Deferred.await from the orElse path since kill(SIGKILL) is
synchronous on Linux — the kernel has already freed the PID and closed FDs
before the syscall returns, making the wait redundant.
… hang

The exit-signal Deferred was resolved only on the Node.js 'close' event, which
requires all pipe file descriptors to be closed. When pkill -f pattern matches
the shell process itself (e.g., pkill -f vim where the shell command line
contains 'vim'), the shell is killed but orphaned children (from shell init
files or the pkill process itself) may still hold pipe FDs, preventing 'close'
from ever firing.

Resolve the Deferred on 'exit' instead — the exit event fires as soon as the
process terminates regardless of pipe state. The 'close' handler is kept as a
safety fallback.

Output consumption via handle.all is independent and runs in a separate fiber,
so resolving earlier does not cause data loss.
@github-actions github-actions Bot added the needs:compliance This means the issue will auto-close after 2 hours. label May 4, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 4, 2026

The following comment was made by an LLM, it may be inaccurate:

I found a potentially related PR:

PR #24783: "fix: add exit event fallback for child process close hang on Windows"
#24783

This appears to be related because it also addresses similar issues with child process lifecycle events (exit vs close events). However, PR #24783 specifically targets Windows, while the current PR #25672 focuses on the pkill -f orphaning issue and resolves on the exit event instead of close.

The two PRs may be addressing complementary aspects of the same underlying problem with process event handling, so it's worth checking if they have overlapping changes or if one supersedes the other.

@github-actions github-actions Bot removed the needs:compliance This means the issue will auto-close after 2 hours. label May 4, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 4, 2026

Thanks for updating your PR! It now meets our contributing guidelines. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

pkill -f command causes tool call hang in opencode TUI

1 participant