haochen bde5f2d090
fix(sandbox): close pipe write fds once when Popen fails (#7394)
* fix(sandbox): close pipe write fds once when Popen fails

The command runners closed the pipe write descriptors twice on the
spawn-failure path: the except block released all four pipe fds, then
the finally block closed the two write fds again. In a busy gateway
another thread can claim a freed descriptor number between the two
closes, so the second os.close silently closed an unrelated descriptor
(a concurrent command's capture pipe or an HTTP socket). Guard the
parent's write-end close on a successful spawn.

* fix(sandbox): release pipe fds on BaseException and scope the Windows runner test

Review follow-up on #7394:
- Catch BaseException in both command runners' spawn-failure cleanup so a
  KeyboardInterrupt mid-spawn still releases each pipe fd exactly once;
  the guarded finally keeps the no-double-close guarantee.
- Skip the _run_windows_command failure-path param on non-Windows
  runners: it reads subprocess.CREATE_NEW_PROCESS_GROUP when building
  the call, which raises AttributeError on POSIX and would fail Linux CI.
- Add a KeyboardInterrupt regression test (fd-per-fd close accounting).

---------

Co-authored-by: Zhangchenhao-111 <285911435+Zhangchenhao-111@users.noreply.github.com>
2026-10-24 16:39:22 +08:00
..