Skip to content

fix(shell): prevent hang when ShellTool.Kill fails with Win32Exception#1021

Merged
Aaronontheweb merged 1 commit into
netclaw-dev:devfrom
Aaronontheweb:fix/shell-execute-kill-failure-hang
May 16, 2026
Merged

fix(shell): prevent hang when ShellTool.Kill fails with Win32Exception#1021
Aaronontheweb merged 1 commit into
netclaw-dev:devfrom
Aaronontheweb:fix/shell-execute-kill-failure-hang

Conversation

@Aaronontheweb
Copy link
Copy Markdown
Collaborator

Summary

PR #1019 fixed the shell_execute orphaned-subprocess hang by moving to WaitForExitAsync and handling outer cancellation. One gap remains: if process.Kill(entireProcessTree: true) throws Win32Exception (the OS refuses the kill), the handler logs the error and then immediately awaits Task.WhenAll(stdoutTask, stderrTask). Since the process may still be alive and holding the pipes open, those ReadToEndAsync calls never hit EOF — recreating the exact hung-tool-call failure mode.

Changes

  • ShellTool.cs — in the Win32Exception path, dispose StandardOutput/StandardError so the pipe reads complete promptly instead of blocking forever; wrap Task.WhenAll in a catch for the expected IOException/ObjectDisposedException.
  • ShellToolTests.cs — tighten the Caller_cancellation_* test to spawn a child-process tree (sleep 120 & wait on Unix) so it actually exercises the entireProcessTree kill path and would hang if the tree-kill regressed.

Test plan

  • dotnet test ShellTool — 23/23 pass
  • dotnet slopwatch analyze — 0 issues
  • File header check — all present

ShellTool's cancellation handler assumes process.Kill() always succeeds.
When Kill() throws Win32Exception (OS refuses the kill), the code logged
the error and immediately awaited ReadToEndAsync on both pipes. If the
child process is still alive and holding stdout/stderr open, those reads
never hit EOF — recreating the exact hung-tool-call failure mode this
PR was meant to fix.

Fix: close StandardOutput/StandardError in the Win32Exception path so
pipe reads drain immediately instead of blocking forever.

Also tighten the regression test to spawn a child-process tree (Unix:
'sleep 120 & wait') so it actually exercises the entireProcessTree
kill path rather than a lone sleep.
@Aaronontheweb Aaronontheweb merged commit b4226ec into netclaw-dev:dev May 16, 2026
12 checks passed
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.

1 participant