Skip to content

fix: survive transient accept() failures instead of exiting#31

Merged
tobez merged 5 commits into
mainfrom
accept-failure-survival
Jul 8, 2026
Merged

fix: survive transient accept() failures instead of exiting#31
tobez merged 5 commits into
mainfrom
accept-failure-survival

Conversation

@tobez

@tobez tobez commented Jul 8, 2026

Copy link
Copy Markdown
Owner

do_accept() croaked on any accept() failure, so transient errors — fd
exhaustion (EMFILE/ENFILE) or a client aborting mid-handshake
(ECONNABORTED) — took the whole daemon down. In production deployments
under fd pressure this turns a momentary resource blip into a full outage.

Now recoverable errno values (EINTR, ECONNABORTED, EAGAIN/EWOULDBLOCK,
EPROTO, EMFILE, ENFILE, ENOBUFS, ENOMEM) get a throttled warning
(new LTC_ACCEPT_FAILURE standalone category, reusing the log-throttling
machinery from #29) and the daemon keeps serving; anything else still
croaks, since remaining accept() errno values indicate programming errors.

Known trade-off: while EMFILE persists the listener stays readable and the
event loop spins; that transient CPU cost is strictly better than exiting,
and a reserve-fd accept-then-close scheme was deliberately left out (YAGNI).

Test plan:

  • new t/accept-failure.t: daemon under RLIMIT_NOFILE=16 driven into
    EMFILE — logs the warning, stays alive, keeps serving the existing
    connection, and accepts new clients once fds free up
  • make test (full suite)
  • scan-build clean

@tobez tobez merged commit b0f5be8 into main Jul 8, 2026
3 checks passed
@tobez tobez deleted the accept-failure-survival branch July 8, 2026 13:49
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