Skip to content

fix: stop a closed FakeServer from accepting one last connection - #25

Merged
9bany merged 1 commit into
masterfrom
fix-python-refused-connection-race
Sep 5, 2026
Merged

9bany merged 1 commit into
masterfrom
fix-python-refused-connection-race

Conversation

@9bany

@9bany 9bany commented Sep 5, 2026

Copy link
Copy Markdown
Member

test_a_refused_connection_provably_never_arrived fails intermittently on CI with Unknown: [Errno 104] Connection reset by peer; the request was written in full and the outcome is not known - which is the opposite of what it asserts.

The test wants a port nobody is listening on, and builds one by starting a FakeServer and closing it. But close set a flag and shut the socket without joining the accept thread, and that thread is parked inside accept(). Closing a socket from another thread does not reliably wake a thread already blocked there, so the listener could outlive close by however long it took to notice. A client connecting in that window is accepted by a server that was supposed to be gone; with an empty script the handler reads the request in full and returns, dropping the connection. The client has written everything and cannot know whether it landed, which is exactly Unknown.

Fixed twice over, because the fixture bug is worth removing on its own:

  • The test binds a socket, takes its port and closes it without ever calling listen. Nothing can be accepted on a socket that never listened, so the refusal is not a race.
  • FakeServer now puts a timeout on the listening socket so the accept loop wakes to re-read its stop flag, and close joins the thread. After it returns, the server really has stopped - which is what every other test using it already assumed.

Not a client bug: Unknown was the correct thing to report for what actually happened on the wire.

`test_a_refused_connection_provably_never_arrived` fails intermittently on
CI with `Unknown: [Errno 104] Connection reset by peer; the request was
written in full and the outcome is not known` - which is the opposite of
what it asserts.

The test wants a port nobody is listening on, and builds one by starting a
FakeServer and closing it. But `close` set a flag and shut the socket
without joining the accept thread, and that thread is parked inside
`accept()`. Closing a socket from another thread does not reliably wake a
thread already blocked there, so the listener could outlive `close` by
however long it took to notice. A client connecting in that window is
accepted by a server that was supposed to be gone; with an empty script
the handler reads the request in full and returns, dropping the
connection. The client has written everything and cannot know whether it
landed, which is exactly `Unknown`.

Fixed twice over, because the fixture bug is worth removing on its own:

- The test binds a socket, takes its port and closes it without ever
  calling `listen`. Nothing can be accepted on a socket that never
  listened, so the refusal is not a race.
- `FakeServer` now puts a timeout on the listening socket so the accept
  loop wakes to re-read its stop flag, and `close` joins the thread. After
  it returns, the server really has stopped - which is what every other
  test using it already assumed.

Not a client bug: `Unknown` was the correct thing to report for what
actually happened on the wire.
@9bany
9bany merged commit 4409c2c into master Sep 5, 2026
19 of 20 checks passed
@9bany
9bany deleted the fix-python-refused-connection-race branch September 7, 2026 02:29
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