182390b4

By: Tom Sydney Kerckhove <syd@cs-syd.eu>

warp: tell the caller when the accept loop loses its listener

acceptNewConnection returns Nothing on any errno other than eCONNABORTED or
eMFILE, which ends acceptLoop and hands runSettings a plain (). That is also
exactly what a graceful shutdown returns, so a server that can no longer accept
is indistinguishable from one that was asked to stop. Whatever supervises it
never learns that it is dead, and it sits there holding a socket it will never
accept on again.

settingsOnException is called on the way out, so it is not silent in the logs,
but a log line is not a return value: there is nothing for the caller to branch
on.

It cannot simply rethrow, because closing the listening socket is the
documented way to end the loop. That arrives as an InvalidArgument, which warp
already reads as the socket going away in the normal course of running: see
defaultShouldDisplayException, and the recv handler in socketConnection, which
both treat it that way. So take the same reading here, and rethrow the rest.

Reported before as #603, which was closed by the eMFILE retry branch. That
handles running out of descriptors in this process; the silent stop on every
other errno stayed.

AcceptFailureSpec pins both directions, since a fix that turned deliberate
shutdowns into exceptions would be worse than the bug: closing the listening
socket on purpose still ends the loop quietly, and an accept() that fails with
eNFILE reaches the caller. It also pins waitForDecreased returning
NoConnections when there is nothing to wait for, the eMFILE branch this sits
beside. Master's suite is 121 examples and 0 failures; with this it is 124 and
0. Keeping the tests and reverting only the change to acceptNewConnection gives
124 examples and exactly 1 failure.

Version 3.4.15.1 as a bug fix, though it is arguably CONTRIBUTING's "changing
behavior of existing public API": runSettings throws where it used to return.
Anyone relying on the old behaviour is relying on not being told their server
is dead.

Suite timing

Time to Start Worker time Duration Time to finish Idle
Config 0s 1s 1s 1s 0s
Eval - - - - -
Build - - - - -
Suite 0s 1s 1s 1s 0s

Timeline

0s