Severity: low / enhancement — analysis + prototype; kernel-level per-op timeouts for the client side.
What it is
IORING_OP_LINK_TIMEOUT (opcode 15, kernel 5.5+): set IOSQE_IO_LINK on a parent SQE and follow it immediately with a LINK_TIMEOUT SQE carrying a timespec. Semantics:
- Parent completes first → parent posts its normal CQE; the timeout posts
-ECANCELED.
- Timeout fires first → the kernel cancels the parent (parent posts
-ECANCELED); the timeout posts -ETIME.
Either way the "everything is a CQE" invariant holds — timeouts and cancellations resolve through the normal dispatch path (see the level-3 liveness discussion in #104: a recv on a silent-but-alive peer is a legitimate forever-pending op; only timeouts convert eventually into boundedly).
Where it fits
- Client ops (
SubmitClientOpCore, Reactor.RingHost.cs#L92-L105): an optional per-op deadline gives pg/redis/file commands kernel-precision timeouts instead of the 250 ms ticker sweep granularity, with zero userspace bookkeeping on the happy path, and it keeps working even if tickers are wedged.
- Connect timeouts for the client pools — the most natural first user (
CONNECT + linked timeout).
Where it does NOT fit
Costs to weigh
- +1 SQE and +1 CQE per covered op. The success-path noise (
-ECANCELED on the unused timeout) is a failure code, so IOSQE_CQE_SKIP_SUCCESS (companion issue) cannot suppress it — route it via a dedicated user_data kind and ignore, like cancels.
- The timespec must stay alive until the timeout's CQE — store it in the client op slot alongside the completion.
IOSQE_IO_LINK constrains in-ring ordering of the pair (fine — they're adjacent by construction).
Suggested plan
Prototype on the PgConnection command path behind PgOptions.CommandTimeout; measure SQE/CQE overhead vs. the sweep's 250 ms precision win; keep the ticker sweep as the coarse backstop and decide replace-vs-layer with data. Counters from #101 make the overhead visible.
Severity: low / enhancement — analysis + prototype; kernel-level per-op timeouts for the client side.
What it is
IORING_OP_LINK_TIMEOUT(opcode 15, kernel 5.5+): setIOSQE_IO_LINKon a parent SQE and follow it immediately with a LINK_TIMEOUT SQE carrying a timespec. Semantics:-ECANCELED.-ECANCELED); the timeout posts-ETIME.Either way the "everything is a CQE" invariant holds — timeouts and cancellations resolve through the normal dispatch path (see the level-3 liveness discussion in #104: a recv on a silent-but-alive peer is a legitimate forever-pending op; only timeouts convert eventually into boundedly).
Where it fits
SubmitClientOpCore, Reactor.RingHost.cs#L92-L105): an optional per-op deadline gives pg/redis/file commands kernel-precision timeouts instead of the 250 ms ticker sweep granularity, with zero userspace bookkeeping on the happy path, and it keeps working even if tickers are wedged.CONNECT+ linked timeout).Where it does NOT fit
Costs to weigh
-ECANCELEDon the unused timeout) is a failure code, soIOSQE_CQE_SKIP_SUCCESS(companion issue) cannot suppress it — route it via a dedicated user_data kind and ignore, like cancels.IOSQE_IO_LINKconstrains in-ring ordering of the pair (fine — they're adjacent by construction).Suggested plan
Prototype on the
PgConnectioncommand path behindPgOptions.CommandTimeout; measure SQE/CQE overhead vs. the sweep's 250 ms precision win; keep the ticker sweep as the coarse backstop and decide replace-vs-layer with data. Counters from #101 make the overhead visible.