Skip to content

Add windows support - #231

Open
ryanofsky wants to merge 7 commits into
bitcoin-core:masterfrom
ryanofsky:pr/win
Open

Add windows support#231
ryanofsky wants to merge 7 commits into
bitcoin-core:masterfrom
ryanofsky:pr/win

Conversation

@ryanofsky

@ryanofsky ryanofsky commented Oct 22, 2025

Copy link
Copy Markdown
Collaborator

Add support for running on windows. These changes make the libmultiprocess API more generic, using stream types instead of file descriptors. All features are supported, including spawning processes with socket connections to the parent process. These changes were originally made in bitcoin/bitcoin#32387

@DrahtBot

DrahtBot commented Oct 22, 2025

Copy link
Copy Markdown

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Reviews

See the guideline and AI policy for information on the review process.

Type Reviewers
Approach ACK hebasto, ViniciusCestarii

If your review is incorrectly listed, please copy-paste <!--meta-tag:bot-skip--> into the comment that the bot should ignore.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #312 (util: report back child errors to parent and throw by ViniciusCestarii)
  • #298 (Fix error handling when creating clients (mp::ConnectStream) by xyzconstant)
  • #212 (ci: add newdeps job testing newer versions of cmake and capnproto by ryanofsky)

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

LLM Linter (✨ experimental)

Possible typos and grammar issues:

  • It it possible -> It is possible [“it” is duplicated, which breaks the sentence]

2026-07-30 21:05:42

@ryanofsky

Copy link
Copy Markdown
Collaborator Author

Rebased 7d2f3c4 -> 2975fac (pr/win.1 -> pr/win.2, compare) due to conflicts with #237

@pavlenex

pavlenex commented Apr 8, 2026

Copy link
Copy Markdown

We have miners using Stratum V2 that are on Windows and would like to see Windows IPC support landing, is there any estimate when they can expect this to materialize? We have a dozen of users who can help with testing if that's a blocker.

@Sjors

Sjors commented Apr 8, 2026

Copy link
Copy Markdown
Member

@pavlenex testing would definitely be useful. I guess for that to work we'd need a stack of pull requests: this one here in libmultiprocess, one in Bitcoin Core that enables IPC support in the Windows Guix build, and then an SRI pull request that uses it. Testers would then have download (or build themselves) the custom bitcoin core and SRI binaries.

I've added Windows support to my v32 wish list: bitcoin/bitcoin#33777

No guarantees obviously.

@ryanofsky

Copy link
Copy Markdown
Collaborator Author

I'll try to get this PR ready for review this week, split up into smaller commits and with ci passing. From there as Sjors mentioned there is a lot more work to do: more code changes in bitcoin/bitcoin#32387 that need to be made in bitcoin core, enabling IPC into windows builds in bitcoin core, enabling it in windows CI jobs with pycapnp, adding client support, probably adding a windows CI job to this repository.

v32 sounds like a good target though and it is very useful to know there is demand for this feature, because it hasn't been a priority so far

@ryanofsky

ryanofsky commented Apr 15, 2026

Copy link
Copy Markdown
Collaborator Author

PR is split up into commits now and should be reviewable. CI is not passing but failures look like IWYU errors. I also opened bitcoin/bitcoin#35084 with corresponding bitcoin core changes. Windows support for bitcoin core can be tested with bitcoin/bitcoin#32387 which combines both PRs and enables IPC by default in windows builds.

Rebased 2975fac -> cb16d2e (pr/win.2 -> pr/win.3, compare) splitting changes up into more reviewable commits

Updated cb16d2e -> e563c96 (pr/win.3 -> pr/win.4, compare) to fix various ci failures #231 (comment): macos/freebsd shutdownwrite fail, bitcoin core ci jobs api incompatibility, iwyu and olddeps fixes

Updated e563c96 -> d9fcac6 (pr/win.4 -> pr/win.5, compare) to fix IWYU errors https://github.com/bitcoin-core/libmultiprocess/actions/runs/24539430990/job/71741856575?pr=231

Added 1 commits d9fcac6 -> a1748e2 (pr/win.5 -> pr/win.6, compare) to fix bitcoin core macos exception type error https://github.com/bitcoin-core/libmultiprocess/actions/runs/24541950788/job/71749481354?pr=231

Updated a1748e2 -> 18fc188 (pr/win.6 -> pr/win.7, compare) with updates from bitcoin/bitcoin#32387 pr/ipc-win.23

Updated 18fc188 -> 7fd5ec4 (pr/win.7 -> pr/win.8, compare) adding workaround for ubuntu packaging bug exposed by cmake change https://github.com/bitcoin-core/libmultiprocess/actions/runs/24746487506/job/72399345861, also fixing olddeps include and iwyu errors https://github.com/bitcoin-core/libmultiprocess/actions/runs/24746487510, also fixing more MSVC errors, and rearranging commits

@Sjors

Sjors commented Apr 20, 2026

Copy link
Copy Markdown
Member

How realistic is it to add a Windows CI job here? (can be cross-compiled)

This was referenced Apr 20, 2026
Sjors added a commit to Sjors/sv2-tp that referenced this pull request Apr 20, 2026
The lifecycle test repeatedly constructs and destroys TPTester to
exercise IPC EventLoop teardown. On Windows it hangs intermittently
in std::thread::join during teardown of libmultiprocess thread-local
state. This is a known libmultiprocess Windows issue, not specific
to sv2-tp:

  bitcoin-core/libmultiprocess#231
  bitcoin/bitcoin#32387

The fix lives upstream and rewrites the EventLoop wakeup primitive
(raw fd -> KJ stream) and adds shutdownWrite() in ~Connection. Until
that lands and is backported into our libmultiprocess subtree, gate
this particular test off on _WIN32. The other sv2 unit tests run
normally on Windows; only the explicit teardown loop is affected.

Assisted-by: GitHub Copilot
Assisted-by: Anthropic Claude Opus 4
Sjors added a commit to Sjors/sv2-tp that referenced this pull request Apr 20, 2026
The template_provider_tests `client_tests`, `fee_timer_blocking_test`
and `new_tip_bypasses_fee_timer_test` cases each construct and tear
down a TPTester. Like the lifecycle test skipped in the previous
commit, that teardown deadlocks intermittently on Windows in
std::thread::join during libmultiprocess thread-local state cleanup.
This is a known libmultiprocess Windows issue, not specific to
sv2-tp:

  bitcoin-core/libmultiprocess#231
  bitcoin/bitcoin#32387

Gate the three TPTester-using cases off on _WIN32 with a TODO. The
non-IPC test `block_reserved_weight_floor` continues to run on
Windows.

Assisted-by: GitHub Copilot
Assisted-by: Anthropic Claude Opus 4
@ryanofsky

ryanofsky commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator Author

This PR is rebased after the #274 merge, so should be ready for review now. It does look like fixes will be needed for CI, though, and I'm working on that.

Note my goal with this PR is just to add a basic level of windows support so libmultiprocess cross-compiles with mingw and spawn and listen tests run in wine. More followups will probably be needed after this to fix any problems that arise with MSVC support or enabling IPC in windows builds for Bitcoin core. The full PR targeting all of that is bitcoin/bitcoin#32387 and has some unresolved issues still.

The downstream PR bitcoin/bitcoin#35084 updating Bitcoin core to use the newer libmultiprocess API is also ready for review and can be reviewed in parallel to this.


Rebased 7fd5ec4 -> 259f010 (pr/win.8 -> pr/win.9, compare) after #274

Updated 259f010 -> c0bc409 (pr/win.9 -> pr/win.10, compare) making listen_tests fixes and enabling wine CI job

Updated c0bc409 -> 5a707dc (pr/win.10 -> pr/win.11, compare) to fix windows CI nix errors https://github.com/bitcoin-core/libmultiprocess/actions/runs/29765222110/job/88429702800?pr=231

@Sjors Sjors left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some feedback on the first commit.

Comment thread include/mp/util.h
Comment thread include/mp/util.h
Comment thread include/mp/util.h Outdated
//! Returns child process id and socket id.
//!
//! The connection string is just a file descriptor number on unix, and the
//! child process can call SpawnProcess to parse it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In 37a2190 Improve SpawnProcess API and documentation: did you mean StartSpawned instead of SpawnProcess?

//! The connection string is just a file descriptor number on unix, and the 
//! child process can call StartSpawned to get a socket handle from the connection string.

For other reviewers, here's a diagram of how StartSpawned, SpawnProcess and the spawn_argv dance, based on the calculator example:

Image

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re: #231 (comment)

Good catch, fixed StartSpawned references. SpawnProcess and StartSpawned complement each other with SpawnProcess being called by parent and returing socket id, and StartSpawned being called by child and returning socket id.

ConnectStream and ServeStream are also complements of each other with ServeStream wrapping a C++ interface pointer and serving it over a stream, and ConnectStream wrapping a stream and returning a C++ interface pointer.

Usually ConnectStream is paired with SpawnProcess in the parent, and ServeStream is paired with StartSpawned in the child because the parent wants to call C++ methods on some interface provided by the child. But it's also possible to do the reverse and have the parent serve an interface to the child, or to not use Connect and Serve at all and just communicate directly over the socketpair.

@ryanofsky ryanofsky left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review! Am planning to update downstream PR bitcoin/bitcoin#32387 shortly with these changes and other fixes


Updated 5a707dc -> 8a682fe (pr/win.11 -> pr/win.12, compare) with suggested changes and another listen_tests fix

Comment thread include/mp/util.h
Comment thread include/mp/util.h
Comment thread include/mp/util.h Outdated
//! Returns child process id and socket id.
//!
//! The connection string is just a file descriptor number on unix, and the
//! child process can call SpawnProcess to parse it.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re: #231 (comment)

Good catch, fixed StartSpawned references. SpawnProcess and StartSpawned complement each other with SpawnProcess being called by parent and returing socket id, and StartSpawned being called by child and returning socket id.

ConnectStream and ServeStream are also complements of each other with ServeStream wrapping a C++ interface pointer and serving it over a stream, and ConnectStream wrapping a stream and returning a C++ interface pointer.

Usually ConnectStream is paired with SpawnProcess in the parent, and ServeStream is paired with StartSpawned in the child because the parent wants to call C++ methods on some interface provided by the child. But it's also possible to do the reverse and have the parent serve an interface to the child, or to not use Connect and Serve at all and just communicate directly over the socketpair.

@Sjors Sjors left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Roughly reviewed 86aa029 util: Add Windows support. Windows code gives me a headache, but it's nicely constrained to a few places.

Comment thread src/mp/util.cpp
sedited added a commit to bitcoin/bitcoin that referenced this pull request Jul 29, 2026
d3d74e7 ipc, refactor: Update mp::g_thread_context references (Ryan Ofsky)
2d3f72f ipc, refactor: Update mp::SpawnProcess call (Ryan Ofsky)
e9f1981 ipc, refactor: Add Stream type alias and use it (Ryan Ofsky)
3859805 ipc, refactor: Add SocketId type alias and use it (Ryan Ofsky)
2ee9b69 ipc, refactor: Add ProcessId type alias and use it (Ryan Ofsky)
3449797 ipc: Avoid 'unistd.h' error with MSVC (Ryan Ofsky)
dbcc192 ipc, refactor: fix include order (Ryan Ofsky)
7c86d48 ipc, refactor: use native path separators in test (Ryan Ofsky)
00287b9 ipc, refactor: Change Protocol class field order (Ryan Ofsky)
33d37f3 ipc, refactor: Drop connect/listen/serve exe_name parameters (Ryan Ofsky)
7949404 ipc, moveonly: combine ipc_test.cpp and ipc_tests.cpp (Ryan Ofsky)

Pull request description:

  This PR makes Bitcoin Core changes needed to be compatible with bitcoin-core/libmultiprocess#274, which changes the libmultiprocess API to stop using unix-specific types so it is compatible with windows. (Windows support is added in followups: bitcoin-core/libmultiprocess#231 and #32387.)

  The PR uses some [compatibility shims](https://github.com/ryanofsky/bitcoin/blob/pr/ipc-wins/src/ipc/util.h) so it can be reviewed and merged without needing to merge bitcoin-core/libmultiprocess#274 first and bump the libmultiprocess subtree. These can be deleted when the subtree is updated.

  ---

  Review note: All the changes here are refactoring, and you don't really need to know anything about IPC or Windows to review this code. It is also a mostly move-only change (131 lines added, 96 removed, 215 moved)

ACKs for top commit:
  xyzconstant:
    tACK d3d74e7
  enirox001:
    ACK d3d74e7
  Sjors:
    ACK d3d74e7
  ViniciusCestarii:
    re-ACK d3d74e7 tested locally on Linux

Tree-SHA512: cd48708f9fd086ac8127dc75cfaf4bd8f8da81e07d11b2c9e65fd9061ffa33478bffc6fd6fa4b3505e86c6437752578fe6e5bd590c683c3bc9969093103a5608

@ryanofsky ryanofsky left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the reviews!

Updated 8a682fe -> 0d53680 (pr/win.12 -> pr/win.13, compare) fixing CommandLineFromArgv final quoting bug and adding tests. Also cleaning up some casts and and ifdef.

Comment thread include/mp/util.h Outdated
Comment thread src/mp/util.cpp
ryanofsky and others added 7 commits July 30, 2026 11:19
Remove recently introduced SpawnConnectInfo and SpawnConnectInfoToArgsFn type
aliases since they are the same on all platforms and might obscure the fact
that connect info should be treated as an opaque string.

Co-authored-by: Sjors Provoost <sjors@sprovoost.nl>
Co-authored-by: Sjors Provoost <sjors@sprovoost.nl>
Add Windows-specific code to support building and running on Windows:

- util.h: Guard ProcessId/SocketId/SocketError type aliases with WIN32
  ifdefs so they use SOCKET/uintptr_t on Windows and int on Unix.
  Add winsock2.h include on Windows.
- util.cpp: Guard Unix-specific system headers with WIN32 ifdefs. Add
  Windows-specific includes (windows.h, winsock2.h). Guard MaxFd() with
  #ifndef WIN32. Add GetCurrentThreadId() branch in ThreadName(). Add
  win32Socketpair() forward-declare. Add Windows branch in SocketPair()
  using win32Socketpair(). Add CommandLineFromArgv() helper needed to
  construct CreateProcess command lines. Add Windows branch in
  SpawnProcess() using named pipes and WSADuplicateSocket to pass socket
  to child. Add Windows branch in StartSpawned() reading socket from
  named pipe. Add Windows branch in WaitProcess() using
  WaitForSingleObject/GetExitCodeProcess.
- proxy.cpp: Add SocketOutputStream class on Windows (analogous to
  FdOutputStream but using SOCKET/send()). Add Windows branch in
  EventLoop constructor to create m_post_writer using SocketOutputStream.
Remove POSIX and pthread calls from util.cpp to avoid relying on MinGW's POSIX
compatibility layer. This lets code be compiled with MSVC.
Replace POSIX-only headers (sys/socket.h, sys/un.h, unistd.h) with
Windows equivalents (afunix.h via util.h), guard them with #ifdef WIN32,
use TCP sockets instead of Unix sockets for Wine compatibility, replace
mkdtemp/unlink/rmdir with std::filesystem equivalents, and use
SocketId/SocketError types instead of int/-1 for socket handles so the
file compiles and works with MinGW.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
listen_tests.cpp tests fail on Windows with:
  "expected m_fd != SocketError [18446744073709551615 != 18446744073709551615]"

socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) returns INVALID_SOCKET because
WSAStartup() has not been called. The mp library calls WSAStartup() only inside
ConnectSocketToProcess(), which listen_tests.cpp never reaches — it creates
sockets directly using the BSD API.

Fix: add a static initializer that calls WSAStartup(MAKEWORD(2,2), ...) at
program startup before any test runs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- shell.nix: add `windows` parameter that selects pkgs.pkgsCross.mingwW64
  as the cross target; also change crossPkgs default from import<nixpkgs>{}
  to null (cleaner API). When windows=true, add native pkgs.capnproto to
  nativeBuildInputs so capnp/capnpc-c++ are in PATH for cmake code generation,
  and add wine64Packages.staging so ctest can run mptest.exe via wine.
  Change llvmBase to always use pkgs (native) instead of crossPkgs.

- ci/configs/windows.bash: new config that cross-compiles with mingw,
  sets CMAKE_SYSTEM_NAME=Windows, CMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER
  (so cmake finds native capnp from PATH), CMAKE_CROSSCOMPILING_EMULATOR=wine
  (so ctest runs mptest.exe via wine), and sets MPGEN_PRE_BUILD=1.

- ci/scripts/ci.sh: add MPGEN_PRE_BUILD support: when set, build native mpgen
  in $CI_DIR-native before the main cross build, then inject
  -DMPGEN_EXECUTABLE into CMAKE_ARGS. This is needed because cmake's
  add_custom_command does not use CMAKE_CROSSCOMPILING_EMULATOR, so the
  cross-compiled mpgen.exe cannot be used as a code generator directly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@ryanofsky ryanofsky closed this Jul 30, 2026
@ryanofsky ryanofsky reopened this Jul 30, 2026

@hebasto hebasto left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concept and approach ACK.

@ryanofsky

Copy link
Copy Markdown
Collaborator Author

Kino1994 pushed a commit to Kino1994/bitcoin-full-history that referenced this pull request Aug 2, 2026
6101a2e ipc, refactor: Update mp::g_thread_context references (Ryan Ofsky)
8f9f52c ipc, refactor: Update mp::SpawnProcess call (Ryan Ofsky)
ff56e7a ipc, refactor: Add Stream type alias and use it (Ryan Ofsky)
c0a7490 ipc, refactor: Add SocketId type alias and use it (Ryan Ofsky)
56c0011 ipc, refactor: Add ProcessId type alias and use it (Ryan Ofsky)
c4c23f6 ipc: Avoid 'unistd.h' error with MSVC (Ryan Ofsky)
8a9cd6e ipc, refactor: fix include order (Ryan Ofsky)
a75df3e ipc, refactor: use native path separators in test (Ryan Ofsky)
83817f3 ipc, refactor: Change Protocol class field order (Ryan Ofsky)
e93ffef ipc, refactor: Drop connect/listen/serve exe_name parameters (Ryan Ofsky)
4b41ceb ipc, moveonly: combine ipc_test.cpp and ipc_tests.cpp (Ryan Ofsky)

Pull request description:

  This PR makes Bitcoin Core changes needed to be compatible with bitcoin-core/libmultiprocess#274, which changes the libmultiprocess API to stop using unix-specific types so it is compatible with windows. (Windows support is added in followups: bitcoin-core/libmultiprocess#231 and bitcoin/bitcoin#32387.)

  The PR uses some [compatibility shims](https://github.com/ryanofsky/bitcoin/blob/pr/ipc-wins/src/ipc/util.h) so it can be reviewed and merged without needing to merge bitcoin-core/libmultiprocess#274 first and bump the libmultiprocess subtree. These can be deleted when the subtree is updated.

  ---

  Review note: All the changes here are refactoring, and you don't really need to know anything about IPC or Windows to review this code. It is also a mostly move-only change (131 lines added, 96 removed, 215 moved)

ACKs for top commit:
  xyzconstant:
    tACK 6101a2e
  enirox001:
    ACK 6101a2e
  Sjors:
    ACK 6101a2e
  ViniciusCestarii:
    re-ACK 6101a2e tested locally on Linux

Tree-SHA512: cd48708f9fd086ac8127dc75cfaf4bd8f8da81e07d11b2c9e65fd9061ffa33478bffc6fd6fa4b3505e86c6437752578fe6e5bd590c683c3bc9969093103a5608

@ViniciusCestarii ViniciusCestarii left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approach ACK b7e3676.

Looking good, build locally with mingw and ran tests and examples with wine.

I found a couple of issues in SpawnProcess that I think are worth addressing and left some nits.

#include <condition_variable>
#include <csignal>
#include <cstdlib>
#include <functional>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In "Improve SpawnProcess API and documentation" 25443b9

nit: this #include <functional> seems unrelated and isn't needed here.

Comment thread src/mp/util.cpp
STARTUPINFOA si{};
si.cb = sizeof(si);
PROCESS_INFORMATION pi{};
KJ_WIN32(CreateProcessA(/*lpApplicationName=*/nullptr, const_cast<char*>(cmd.c_str()), /*lpProcessAttributes=*/nullptr, /*lpThreadAttributes=*/nullptr, /*bInheritHandles=*/TRUE, /*dwCreationFlags=*/0, /*lpEnvironment=*/nullptr, /*lpCurrentDirectory=*/nullptr, &si, &pi), "CreateProcess failed");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In "util: Add Windows support" 7dcb54d

The Unix branch tries to close all fds that child doesn't need before exec, but the Windows branch leaks everything inheritable with bInheritHandles=TRUE to the child process instead of only the necessary, including the both ends of the socketpair.

Comment thread src/mp/util.cpp
Comment on lines 108 to +260
@@ -183,6 +199,7 @@ std::tuple<ProcessId, SocketId> SpawnProcess(const std::function<std::vector<std
{
auto fds{SocketPair()};

#ifndef WIN32
// Evaluate the callback and build the argv array before forking.
//
// The parent process may be multi-threaded and holding internal library
@@ -236,44 +253,111 @@ std::tuple<ProcessId, SocketId> SpawnProcess(const std::function<std::vector<std
_exit(127);
}
return {pid, fds[1]};
#else
// Create windows pipe to send socket over to child process.
static std::atomic<int> counter{1};
std::string pipe_path{"\\\\.\\pipe\\mp-" + std::to_string(GetCurrentProcessId()) + "-" + std::to_string(counter.fetch_add(1))};
HANDLE pipe{CreateNamedPipeA(pipe_path.c_str(), PIPE_ACCESS_OUTBOUND, PIPE_TYPE_MESSAGE | PIPE_WAIT, /*nMaxInstances=*/1, /*nOutBufferSize=*/0, /*nInBufferSize=*/0, /*nDefaultTimeOut=*/0, /*lpSecurityAttributes=*/nullptr)};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In "util: Add Windows support" 7dcb54d

CreateNamedPipeA sets the flag PIPE_WAIT and then calls ConnectNamedPipe so if the child never connects to the pipe (exits or crashes before), the parent blocks in ConnectNamedPipe forever.

KJ_TEST("SpawnProcess does not hang if child never connects to the pipe")
{
    // The named pipe SpawnProcess uses to hand the socket to the child is
    // created with PIPE_WAIT and ConnectNamedPipe
    // is called without an OVERLAPPED structure. If the child exits, crashes,
    // or is a program that never opens the pipe, that call blocks forever and
    // the parent hangs with no way to recover.
    //
    // Run SpawnProcess on a detached thread so the test can time out instead of
    // hanging the whole suite. The thread is detached rather than joined because
    // a hung SpawnProcess is never joinable; the state it touches is therefore
    // shared by value, and the leaked thread is reclaimed at process exit.
    // Either returning or throwing counts as a pass: the requirement is only
    // that it does not block indefinitely.
    auto done{std::make_shared<std::atomic<bool>>(false)};

    std::thread spawn([done] {
        try {
            const auto [process, socket]{SpawnProcess([](std::string connect_info) -> std::vector<std::string> {
                // A child that runs to completion without ever opening the pipe
                // named by connect_info.
                return {"cmd.exe", "/c", "exit 0"};
            })};
            closesocket(socket);
            CloseHandle(process);
        } catch (...) {
            // SpawnProcess reporting an error is an acceptable outcome; only
            // blocking forever is not.
        }
        done->store(true);
    });
    spawn.detach();

    const auto deadline{std::chrono::steady_clock::now() + FAILURE_TIMEOUT};
    while (!done->load() && std::chrono::steady_clock::now() < deadline) {
        std::this_thread::sleep_for(std::chrono::milliseconds{10});
    }

    KJ_EXPECT(done->load(), "SpawnProcess blocked waiting for a child that never connected");
}

Comment thread src/mp/util.cpp
#else
// Create windows pipe to send socket over to child process.
static std::atomic<int> counter{1};
std::string pipe_path{"\\\\.\\pipe\\mp-" + std::to_string(GetCurrentProcessId()) + "-" + std::to_string(counter.fetch_add(1))};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In "util: Add Windows support" 7dcb54d

nit: R"()" here too, to match the util_tests.cpp

Suggested change
std::string pipe_path{"\\\\.\\pipe\\mp-" + std::to_string(GetCurrentProcessId()) + "-" + std::to_string(counter.fetch_add(1))};
std::string pipe_path{R"(\\.\pipe\mp-)" + std::to_string(GetCurrentProcessId()) + "-" + std::to_string(counter.fetch_add(1))};

Comment on lines 48 to 52
//! FD to ListenConnections().
class UnixListener
class SocketListener
{

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In "test: fix listen_tests to compile and run on Windows" 749e76a

nit: TCP here isn't just a Wine workaround, it's what kj win32Socketpair uses on Windows, so the test matches the real transport.


#ifdef WIN32
// Call WSAStartup before any test runs. Winsock requires WSAStartup before any
// socket call; the mp library calls it inside ConnectSocketToProcess(), but

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In "test: Initialize Winsock in listen_tests.cpp on Windows" 493a4b0

nit: this comment and the commit message mentions ConnectSocketToProcess but it doens't exist in the codebase. The WSAStartup call is in StartSpawned()

Suggested change
// socket call; the mp library calls it inside ConnectSocketToProcess(), but
// socket call; the mp library calls it inside StartSpawned(), but

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.

6 participants