Skip to content

Wait readiness probe - #336

Merged
sgerbino merged 4 commits into
cppalliance:developfrom
sgerbino:fix/wait-readiness-probe
Aug 18, 2026
Merged

Wait readiness probe#336
sgerbino merged 4 commits into
cppalliance:developfrom
sgerbino:fix/wait-readiness-probe

Conversation

@sgerbino

Copy link
Copy Markdown
Collaborator

No description provided.

The reactor backends decided socket wait() completion from cached edge
events, which fail in both directions on edge-triggered backends:

- False negative: a short read completes without hitting EAGAIN and
  consumes the readiness edge with no trace; a subsequent wait(read)
  parks forever although data remains buffered, because EPOLLET/
  EV_CLEAR never re-fire without a new transition.

- False positive: an edge arriving with no op parked latches the
  sticky read_ready flag; a speculative read then drains the socket
  without consuming the flag, and a subsequent wait(read) completes
  immediately on an empty socket. The select backend latches the same
  stale flag despite being level-triggered.

Decide wait completion by asking the kernel instead: probe with a
zero-timeout poll() at initiation (an edge-triggered reactor cannot
report a condition that already holds), re-probe when register_op
consumes a cached ready flag, and re-probe at event dispatch before
completing a parked wait op, keeping it parked on EAGAIN. The probe is
side-effect free; in particular it never reads SO_ERROR, which is
consume-on-read and belongs to whichever operation observes the
failure next. The wait(write) immediate-completion short-circuit is
unchanged.
The file mixed three guard patterns: a body-guarded test compiling to
an empty function on Windows, two definition regions split by a
portable test, and two matching #if blocks in run(). The whole suite
registers nothing on Windows, so the guards exist only for
compilability; use one scheme: whole definitions guarded, one
contiguous POSIX region, one POSIX block in run().
macOS timed out both reactor suites: zero-length datagram sends may be
rejected there (nothing queued, so the wait parks), and POLLHUP
visibility after the reporting read consumed SO_ERROR is a Linux
guarantee. Detect both capabilities at runtime and skip the wait leg
when absent instead of hanging; Linux still enforces the full
regression witness. The raw poll() check also moves both tests into
the POSIX region.
A connect completion decided from SO_ERROR alone reports success for a
handshake still in flight: an in-progress connect also reads 0. The
check is reachable without a genuine post-handshake event — fresh TCP
sockets raise a spurious writable edge at registration, so a loop
iteration between open() and connect() latches a stale write_ready
that register_op consumes mid-SYN_SENT, and the same stale edge can
reach a parked connect through dispatch.

Probe writability with a zero-timeout poll() first and report EAGAIN
to stay parked; SO_ERROR decides only once the socket is actually
writable. The dispatch connect arm re-parks on EAGAIN like every
other op instead of completing unconditionally.

The regression test holds a connect in SYN_SENT deterministically
(backlog-full loopback listener drops the SYN) and drains the ready
queue before cancelling so a falsely posted completion cannot be
masked as canceled at delivery.
@cppalliance-bot

Copy link
Copy Markdown

An automated preview of the documentation is available at https://336.corosio.prtest3.cppalliance.org/index.html

If more commits are pushed to the pull request, the docs will rebuild at the same URL.

2026-08-17 12:43:47 UTC

@cppalliance-bot

Copy link
Copy Markdown

GCOVR code coverage report https://336.corosio.prtest3.cppalliance.org/gcovr/index.html
LCOV code coverage report https://336.corosio.prtest3.cppalliance.org/genhtml/index.html
Coverage Diff Report https://336.corosio.prtest3.cppalliance.org/diff-report/index.html

Build time: 2026-08-17 12:58:32 UTC

@codecov

codecov Bot commented Aug 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 79.82%. Comparing base (1f3d91d) to head (b4cdf5e).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff            @@
##           develop     #336   +/-   ##
========================================
  Coverage    79.82%   79.82%           
========================================
  Files           96       96           
  Lines         5937     5937           
  Branches      1209     1209           
========================================
  Hits          4739     4739           
  Misses         851      851           
  Partials       347      347           

Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 1f3d91d...b4cdf5e. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@sgerbino
sgerbino merged commit 05f0464 into cppalliance:develop Aug 18, 2026
44 checks passed
@github-project-automation github-project-automation Bot moved this from Backlog to Done in Beast2 Aug 18, 2026
@sgerbino
sgerbino deleted the fix/wait-readiness-probe branch August 18, 2026 03:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants