Skip to content

On the shared listen fd one worker takes nearly every connection, always the same one #329

Open

Description

@EdmondDantes

On the shared listen fd — the default outside Linux and FreeBSD, and the second Linux CI run through TRUE_ASYNC_SERVER_SHARED_LISTEN_FD=1 — connections opened one after another go almost entirely to one worker, in a fixed direction. #240 settled that the server promises nothing about which worker accepts; these numbers are of a different kind than #240's single [1,0,8] under taskset -c 0, so they are recorded here rather than by reopening it.

Measured on 2026-09-29

Linux (WSL2, 16 CPUs, idle), 2 workers, 32 connections opened one after another, final split first:second:

Probe Shared listen fd SO_REUSEPORT
WebSocket, no rooms (ws_open + delay(50)) 9:23, 6:26, 7:25, 5:27, 11:21 15:17, 17:15, 22:10, 12:20, 21:11
WebSocket, rooms + subscribe 6:26, 5:27, 2:30, 3:29, 4:28 15:17, 10:22, 16:16, 16:16, 16:16
HTTP keep-alive, request per connection 11:21, 15:17, 17:15, 19:13 ×2, 22:10, 25:7, 26:6, 28:4, 9:23 —
websocket/065's spread helper (publishes between rounds) ends at 0:32 on 2 to 5 runs of 20; otherwise the first worker holds 1 to 3 first round already split

On the shared fd every WebSocket run gives the majority to the second worker; on SO_REUSEPORT the direction varies. The cause is not traced. What would establish it: the same probe with 3 workers (does the last one always win), and strace -f -tt -e trace=epoll_wait,accept4 recording, per connection, whose epoll_wait returns first and whose accept4 gets EAGAIN.

Consequence

On macOS, where the shared fd is the default, setWorkers(N) serves sequential clients with essentially one worker. websocket/064–066, which need a subscriber on every worker, now skip on the shared fd (they failed there three times in two runs of PR #328).

Question

Does "the server promises nothing about the accept split" (#240) still hold with this measurement, or is an even-enough split on the shared fd a goal? No fix is proposed before the cause is traced.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions