#36105 bitcoin wrapper: Fix Windows exec so wrapper waits for child process

full analysis

https://github.com/bitcoin/bitcoin/pull/36105 · ryanofsky · +38/-20 in 6 files, 4 commits · labels: none

Goal

  • Make the Windows bitcoin wrapper wait for child processes to finish and propagate their exit codes
  • Allow test frameworks and caller scripts on Windows to capture output and monitor child exit status

Fixes `util::ExecVp` on Windows by switching from `_execvp` to `_spawnvp(_P_NOWAIT)` paired with `_cwait`, ensuring `bitcoin.exe` waits for child processes to finish and forwards their exit status. Works around an MSVCRT difference where nonexistent paths return `EINVAL` instead of `ENOENT`, switches `system_error` to `generic_category` for POSIX `errno` codes, and enables previously skipped functional tests on Windows.

Problem: On Windows, `bitcoin.exe` previously spawned child processes asynchronously and exited immediately with code 0. This prevented scripts and test frameworks from capturing child process output or detecting child failure exit codes.

Category: IPC / multiprocess (#15 of 20)

P3 · platform fix

  • P3 because it fixes child process tracking required for multiprocess coordination on Windows
  • Unblocks Windows multiprocess tooling and functional test execution

The bitcoin wrapper binary is an integral component of the multiprocess process management tooling. Fixing child process execution on Windows ensures reliable process supervision and enables test coverage for multiprocess setups on Windows.

Membership: Touches src/bitcoin.cpp which implements the multiprocess wrapper binary and process dispatch logic.

Factors: security/stability 1, bug 1, performance 0, user value 1, leverage 1

Category: Tools and scripts (#5 of 22)

P3 · bug fix

  • P3 because the Windows CLI wrapper terminated immediately instead of awaiting subcommands
  • Enables scripts and users on Windows to receive accurate exit codes and output

Directly fixes a functional bug in the bitcoin wrapper tool on Windows, where scripts invoking the wrapper received premature exit code 0 rather than waiting for the child process and propagating its exit status.

Membership: Modifies the bitcoin wrapper executable behavior and its functional tests (tool_bitcoin.py).

Factors: security/stability 0, bug 1, performance 0, user value 2, leverage 1

Category: Utilities (logging, arguments, libraries) (#33 of 66)

P3 · platform fix

  • Improves shared utility infrastructure in src/util/exec.cpp by ensuring process launching functions on Windows behave consistently with expectations, waiting on child handles and mapping error categories properly.

Improves shared utility infrastructure in src/util/exec.cpp by ensuring process launching functions on Windows behave consistently with expectations, waiting on child handles and mapping error categories properly.

Membership: Changes util::ExecVp in src/util/exec.cpp and fixes errno categorization across platforms.

Factors: security/stability 0, bug 1, performance 0, user value 1, leverage 0

Reviewability: Ready

  • Ready to review
  • All CI checks are passing and recent review comments have been addressed

The PR passes CI, has clean merge status, and has no blocking change requests pending.

Author status: Active; addressed initial review comments with force-pushes up to 2026-09-09.

Open concerns:

  • Reviewers discussed whether AI attribution tags comply with doc/AI_POLICY.md or should be formatted as attribution text in commit messages (hodlinator, maflcko)
  • Observation that MSVCRT still reports 'Invalid argument' when the final lookup candidate is missing because EINVAL is not mapped to ENOENT in the fallback throw (cyb3ralbert)

Resolved concerns:

  • Commit message wide-character references (_wspawnvp/_wexecvp) were corrected by author push (hodlinator, ryanofsky)
  • Handling of child exit code -1 disambiguated from spawn failure by switching to _spawnvp(_P_NOWAIT) and _cwait (ryanofsky)

Agreement: Mild

  • Strong support for fixing Windows child process waiting without objections to the approach
  • Concept approval and runtime error handling review (hodlinator)
  • Concept approval with notes on future UCRT transitions (hebasto)
  • Collaborated on child exit code resolution logic (Bortlesboat)

Mild: nonblocking objection open (cyb3ralbert)

Multiple maintainers and regular reviewers support the fix and have tested the behavior on Windows; peripheral feedback concerned commit metadata and build environment specifics rather than the implementation approach.

  • hebasto: Concept ACK (2026-08-27)
  • hodlinator: Concept ACK (2026-08-31) and positive review (2026-09-10)

Objections:

ReviewerKindHarmStatusBlockingAuthor repliedQuote
cyb3ralbertinterfaceon MSVCRT builds, missing executables report an unhelpful 'Invalid argument' error instead of 'No such file or directory'opennono2026-09-13: "When the target executable is missing, the error the user sees differs between runtimes: MSVCRT: Error: execvp failed to execute '...\bitcoind': Invalid argument / UCRT: Error: execvp failed to execute '...\bitcoind': No such file or directory... Mapping EINVAL to ENOENT in that throw as well would make an MSVCRT build report a missing file the same way UCRT does, instead of 'Invalid argument'."

Support:

  • hebasto: Concept ACK on fixing the Windows wrapper execution behavior.
  • hodlinator: Concept ACK and verified behavior on Windows environments.

Participants: hebasto (support), hodlinator (support), cyb3ralbert (objection), maflcko (neutral)

State derived from the lists: nonblocking objection open (cyb3ralbert) (model's own read: Strong)

Review verdicts (DrahtBot): 0

Dependencies

Enables:

Base for: #36190

Files

29 lines under test/bench/ci.

  • src/bitcoin.cpp +16/-1
  • test/functional/interface_gui.py +6/-7
  • src/util/exec.cpp +11/-1
  • test/functional/tool_bitcoin.py +0/-11
  • test/functional/test_framework/test_framework.py +4/-0
  • test/config.ini.in +1/-0

Card

This PR fixes `util::ExecVp` and the `bitcoin` wrapper executable on Windows so it waits for child processes to finish and forwards their exit status instead of exiting prematurely with 0. This resolves a known issue where automated scripts and test harnesses on Windows could not capture wrapper output or exit codes, allowing tests like `tool_bitcoin.py` to be unskipped. Reviewers have Concept ACKed the change and assisted with runtime error nuances across MSVCRT and UCRT. The PR is in a ready state with no blocking objections.

Data

dossier JSON · extract JSON · model openrouter/google/gemini-3.8-flash, generated 2026-09-17T21:47, confidence high, input hash 092d31145851278e