Skip to content

Sockets: add the POSIX ServerSocket - #1793

Merged
Mysticial merged 7 commits into
mainfrom
sockets-server-posix
Nov 1, 2026
Merged

Mysticial merged 7 commits into
mainfrom
sockets-server-posix

Conversation

@pa-devbot

@pa-devbot pa-devbot commented Oct 31, 2026 •

Copy link
Copy Markdown
Collaborator

Based on the PR for the Qt ServerSocket + test harness (merge that one first, then rebase this onto main).

Adds ServerSocket_POSIX (an accept-loop thread plus one connection
thread at a time, both from the given thread pool via plain
dispatch(), non-blocking sockets) and enables the POSIX instantiation
of the loopback tests on non-Windows.

Design

  • close()/close_connection() only flip the state; the connection
    thread notices within ~1 ms and closes the socket itself, so
    close_connection() is safe to call from within a listener callback.
  • The accept loop keeps running while a connection is active and
    rejects new clients via on_connect_rejected (one connection at a
    time).
  • The connection task is started and published without holding the
    main lock
    : assigning to the task slot destroys the previous
    connection task's AsyncTask, whose destructor waits for that task
    to finish - and the task may be blocked on the main lock. Holding the
    lock across the assignment deadlocks (found while testing).

Tests: the 7 loopback scenarios (echo, zero-length send, 1 MiB
transfer, rapid reconnects, send/close race, reject second client,
port in use) now run against the POSIX backend on non-Windows in
addition to Qt. Verified: 14/14 socket tests pass on Linux, plus a
standalone POSIX harness (39 checks) and repeated stress runs.

Note (rebuild on current main): the implementation now lives in ServerSocket_POSIX.cpp, mirroring the client header/.cpp split (#1795). Also fixes an implicit size_t -> int narrowing in the send loop that -Wshorten-64-to-32 rejected on the Mac CIs.

Update (Mac CI): the 1 MiB "Large transfer" test failed on both Mac
CIs with "The client did not send all 1048576 bytes": macOS send()
with MSG_DONTWAIT readily returns after a partial write when the
kernel's send buffer is full (Linux usually does not), and
ClientSocket_POSIX::send() returned early on a partial send. It now
loops until the whole buffer is written, matching the Qt backend.
Verified with the standalone POSIX harness.

Update (formatting): fixed ServerSocket_POSIX.cpp indentation
left over from the header/.cpp split (method bodies had kept their
in-class 8-space indent). The Mutex/ConditionVariable wrapper
migration from #1787 comes in with the rebase.

@pa-devbot
pa-devbot force-pushed the sockets-server-posix branch from cda953d to 2b873c2 Compare November 1, 2026 01:42
@pa-devbot
pa-devbot force-pushed the sockets-server-loopback branch from 82d5b0f to 544b9fb Compare November 1, 2026 02:44
@pa-devbot
pa-devbot force-pushed the sockets-server-posix branch 2 times, most recently from b4e7522 to e7cd420 Compare November 1, 2026 03:23
@pa-devbot
pa-devbot force-pushed the sockets-server-loopback branch from 544b9fb to 20140b7 Compare November 1, 2026 04:53
@pa-devbot
pa-devbot force-pushed the sockets-server-posix branch from e7cd420 to 77e2f4f Compare November 1, 2026 04:59
@pa-devbot
pa-devbot force-pushed the sockets-server-posix branch 2 times, most recently from 427b871 to ca15f0a Compare November 1, 2026 09:17
Base automatically changed from sockets-server-loopback to main November 1, 2026 09:35
@pa-devbot
pa-devbot force-pushed the sockets-server-posix branch from ca15f0a to c3a6503 Compare November 1, 2026 09:57
@pa-devbot
pa-devbot force-pushed the sockets-server-posix branch from 1eee4a5 to d5c7b98 Compare November 1, 2026 11:34
@Mysticial
Mysticial force-pushed the sockets-server-posix branch from 5c404ce to a27eda4 Compare November 1, 2026 20:33
pa-devbot and others added 7 commits November 1, 2026 12:34
Implements ServerSocket_POSIX (an accept-loop thread plus one
connection thread at a time, both from the given thread pool via plain
dispatch(), with non-blocking sockets; the implementation lives in
ServerSocket_POSIX.cpp, following the split of the client backends)
and enables the POSIX instantiation of the loopback tests on
non-Windows.

close()/close_connection() only flip the state: the connection thread
notices within ~1 ms and closes the socket itself, so
close_connection() is safe to call from within a listener callback.
The accept loop keeps running while a connection is active and rejects
new clients via on_connect_rejected.

The connection task is started and published without holding the main
lock: assigning to the task slot destroys the previous connection
task's AsyncTask, whose destructor waits for that task to finish - and
the task may be blocked on the main lock.
send() with MSG_DONTWAIT can return after writing only part of the
buffer when the kernel's send buffer is full. macOS does this much
more readily than Linux, so the 1 MiB loopback transfer test failed
on the Mac CI: client.send() returned early with fewer bytes.

Loop until the whole buffer has been written, matching the Qt
backend's send() behavior.
The method bodies kept their in-class 8-space indentation from the
monolithic header; un-dedent them to file scope.
The header/.cpp split left 2-3 blank lines between most members;
normalize to the single-blank style used by the client headers.
Same issue as the WinSocket backend (#1820): the connection thread
called ::recv() inside the m_lock scope. The socket is non-blocking
so it returns immediately in practice, but a socket call must not
stretch the lock across a kernel transition: if the socket were ever
made blocking, every other caller of m_lock (close(),
close_connection(), send(), the accept loop) would hang while the
client stays silent.

The loop now takes m_lock only for the state check, calls recv()
unlocked, and re-checks under the lock that the connection has not
been replaced before dispatching on_receive_data.
@Mysticial
Mysticial merged commit 03c4ae1 into main Nov 1, 2026
6 of 7 checks passed
@Mysticial
Mysticial deleted the sockets-server-posix branch November 1, 2026 20:52
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.

2 participants