Skip to content

Keep listening after a failed accept() in ListenConnections#310

Open
xyzconstant wants to merge 1 commit into
bitcoin-core:masterfrom
xyzconstant:server-disconnect-tests
Open

Keep listening after a failed accept() in ListenConnections#310
xyzconstant wants to merge 1 commit into
bitcoin-core:masterfrom
xyzconstant:server-disconnect-tests

Conversation

@xyzconstant

@xyzconstant xyzconstant commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Following on testing the reversed direction @ryanofsky suggested in #298, I was working on adding tests to cover immediate client disconnects on the server side.

While doing so, an issue surfaced on macOS: the accept() call in ListenConnections fails for the closed connection, causing the server socket to stop accepting further connections. The root cause is that the accept loop is only continued after a successful accept(), on failure the exception is unhandled, so the loop is never resumed.

This PR handles the failure and keeps the accept loop running. Also, it adds a test covering the case.

@DrahtBot

DrahtBot commented Jul 17, 2026

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
ACK ViniciusCestarii

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

@xyzconstant xyzconstant changed the title ListenConnections: keep listening after a failed accept test: add coverage for immediate client disconnects in ListenConnections Jul 17, 2026
@xyzconstant

Copy link
Copy Markdown
Contributor Author

the macos job failed with:

[ TEST ] listen_tests.cpp:292: ListenConnections survives a client that disconnects before being accepted
mp/proxy.cpp:48: error: Uncaught exception in daemonized task.; exception = kj/async-io-unix.c++:1365: failed: setsocketopt(IPPROTO_TCP, TCP_NODELAY): Invalid argument
stack: 1020dc7cb 1020dcaff 1020dcc60 10079556c
/Users/runner/work/libmultiprocess/libmultiprocess/test/mp/test/listen_tests.cpp:189: failed: expected matched
stack: 10078b28b 1007ac7bf

I came across the same issue on my machine (MacBook Pro M2) too. I'll push a fix in a moment.

A failed `accept()` would stop the server from accepting any further
connections, because the accept loop was only continued after a
successful accept.

Handle this by also keeping the accept loop running on failures.
@xyzconstant
xyzconstant force-pushed the server-disconnect-tests branch from f44094f to 38391eb Compare July 17, 2026 01:20
@xyzconstant xyzconstant changed the title test: add coverage for immediate client disconnects in ListenConnections Keep listening after a failed accept() in ListenConnections Jul 17, 2026
@xyzconstant
xyzconstant marked this pull request as ready for review July 17, 2026 02:32

@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.

ACK 38391eb Nice finding! This is nicer than the old code that would just stop listening because of a transient error that KJ didn't catch but also with this change now a non-transient error will spin forever retrying an unrecoverable error which I believe could be fixed in a follow up.

Also I have dug in and I found that this is a KJ bug because it should treat transient errors like this and it was already fixed for capnp v2 which isn't released yet.

Given that, I still think this PR is correct and the defensive retry is the right call regardless. The spin forever on permanent failure case remains a valid follow-up on top of this.

Comment thread include/mp/proxy-io.h
// Keep listening if a single accept() fails, so the server does not
// stop accepting future connections.
[&loop, &init, listener](const kj::Exception& e) {
MP_LOG(loop, Log::Info) << "IPC server: accept 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 "Keep listening after a failed accept in ListenConnections" 38391eb

nit: I believe MP_LOG(loop, Log::Warning) would fit better here and also the kj exception could be logged too

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.

3 participants