Skip to content

fix(session): a failing listener no longer stalls serve (#351) - #356

Merged
lxsaah merged 4 commits into
mainfrom
feat/351-serve-accept-errors
Oct 24, 2026
Merged

lxsaah merged 4 commits into
mainfrom
feat/351-serve-accept-errors

Conversation

@lxsaah

@lxsaah lxsaah commented Oct 24, 2026

Copy link
Copy Markdown
Member

Description

Fixes #351: session::serve logged a failed accept and called accept again at once, and its select is biased toward accept. A listener whose accept failed immediately, every time, kept serve spinning without ever polling its open connections again, and the task couldn't be aborted.

This merges the feature branch feat/351-serve-accept-errors. Each fix was reviewed as its own PR into that branch:

PR What
#353 TransportError::Closed ends accepting: serve serves its open connections to their end and returns
#354 The accept after any other error yields once first (PendingOnce), inside the accept future, so the select falls through to the connections and the task stays cancellable. The Embassy TCP listener's own guard is gone
#355 Repeated failures are summarized: the first one with its error, then at 10/100/1,000/… attempts in a row, and "recovered after N" on the next success
docs Changelogs: aimdb-core, aimdb-embassy-adapter, root

Measurements from the investigation

Listener Open connection Failed accepts
fails immediately, never Pending (before) starved, task not abortable 3.18 million/s
Pending once before each error (the old Embassy workaround) served ~135,000/s, each one logged
real tokio UnixListener with EMFILE (macOS) served 1 in 3 s: edge-triggered readiness, no spinning

So with tokio UDS/TCP, the EMFILE case named in #351 doesn't spin. The affected cases were listeners that fail without Pending (a closed channel, third-party transports) and the Embassy listener, which worked around it by yielding itself.

Behaviour changes

  • serve returns once its listener reports Closed and its last connection has ended (documented on serve). Listeners that never close (UDS, TCP, OneShotListener) keep it running, as before.
  • A failing accept no longer produces one log line per attempt, only the first one, a summary per order of magnitude, and a line when it recovers.

Known gap (documented)

A permanently failing accept still retries without a pause, because serve is deliberately timer-free. It no longer blocks anything and barely logs, but it costs CPU. A real back-off was left out on purpose (option 4 of the analysis).

Tests

  • aimdb-core/tests/session_engine.rs, with a ScriptedListener that hands out one connection and then answers every accept with a fixed error:
    • Closed: the open connection is served, and serve returns after it ends;
    • Io: the open connection is served, and serve can be aborted;
    • all four hang against the code before their fix (killed after 30 s).
  • Unit tests for AcceptFailures (logging at 1/10/100/1000, series end on success, powers of ten).

Verified locally

  • All Makefile tests for aimdb-core, aimdb-client, aimdb-uds-connector, aimdb-tcp-connector (including the Embassy loopback over EmbassyTcpListener), aimdb-serial-connector, aimdb-websocket-connector and aimdb-embassy-adapter.
  • Clippy (-D warnings) for every aimdb-core feature set (including connector-session with tracing/log), and for aimdb-embassy-adapter and aimdb-tcp-connector, including thumbv7em.
  • cargo doc -D warnings for aimdb-core.
  • This is the first full CI run over all of [BUG] session::serve spins on a listener whose accept keeps failing, and starves every open connection #351.

Related Issue

Checklist

  • I have read the CONTRIBUTING.md document.
  • My code follows the project's coding standards.
  • I have added tests to cover my changes.
  • All new and existing tests passed (make check). The affected crates pass locally; the full run is left to CI.
  • I have updated the documentation accordingly.

🤖 Generated with Claude Code

https://claude.ai/code/session_01YPDjQ947yKjLLAq3Xzgu3e

lxsaah and others added 4 commits October 24, 2026 19:36
`aimdb-core` (serve stops accepting on `Closed`, yields before the accept
after any other error, summarizes repeated failures), `aimdb-embassy-adapter`
(the listener's own yield is gone), and the root changelog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YPDjQ947yKjLLAq3Xzgu3e
@lxsaah
lxsaah merged commit 9984558 into main Oct 24, 2026
10 checks passed
@lxsaah
lxsaah deleted the feat/351-serve-accept-errors branch October 24, 2026 18:33
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.

[BUG] session::serve spins on a listener whose accept keeps failing, and starves every open connection

1 participant