Hold host calls inside the bridge so the quiesce is tested, not assumed
The closerace scenario pinned the order of the count and the notify but never that a host call is counted at all. Deleting the call scope from `cultmesh_quic_next_event` outright leaves every configuration green — the pollers finish before the teardown reaches them — and so does inverting the comparison that makes a positive timeout block, which empties the library before the close even begins. A scenario that only sleeps and hopes cannot tell any of that apart from the real thing. So the bridge says it itself, in development builds only (section 7 of the header, behind CULTMESH_QUIC_DEBUG_ASSERTS, absent from every shipped binary): the peak number of host calls counted inside the library, the number counted when the close began its wait, and a hold that parks a call inside the library until the scenario releases it. A held call returns the 0 an empty queue would have and touches the runtime no further, so a bridge that frees the runtime under it is reported by the scenario rather than crashing inside it. `holdclose` drives the quiesce through that seam: the calls are counted, they were still counted when the close began, and the close did not return while they were held. `closerace` keeps hunting the race and now also refuses to pass when a poller left before the close began, which is a scenario that raced nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
51fb449b56
commit
62e53df447
4 changed files with 275 additions and 10 deletions
|
|
@ -308,6 +308,38 @@ CULTMESH_QUIC_API int32_t cultmesh_quic_last_error(
|
|||
* when nothing has failed. */
|
||||
CULTMESH_QUIC_API int32_t cultmesh_quic_last_status(void* runtime);
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* 7. The development seam
|
||||
*
|
||||
* Present only in a library configured with `CULTMESH_QUIC_DEBUG_ASSERTS`, which
|
||||
* a shipped build never is. It exists for the runtime-lifetime scenarios: the
|
||||
* quiesce is a promise about host calls that are inside the library, and a
|
||||
* scenario that can only sleep and hope cannot tell a bridge that counts them
|
||||
* from one that does not.
|
||||
*
|
||||
* It is process-wide, not per-runtime, because the numbers outlive the runtime
|
||||
* they describe: `cultmesh_quic_runtime_close` frees the runtime, and the count
|
||||
* it waited on is read afterwards. The scenarios open one runtime at a time.
|
||||
* --------------------------------------------------------------------------- */
|
||||
#if defined(CULTMESH_QUIC_DEBUG_ASSERTS)
|
||||
|
||||
/* Non-zero arms the hold and resets both counters: every call that reaches the
|
||||
* blocking wait in `cultmesh_quic_next_event` parks inside the library instead
|
||||
* of returning. Zero releases every held call and disarms it. A held call
|
||||
* returns 0 and touches the runtime no further. */
|
||||
CULTMESH_QUIC_API void cultmesh_quic_debug_hold_calls(int32_t hold);
|
||||
|
||||
/* The high-water mark of host calls counted inside the library since the hold
|
||||
* was armed. Zero means no call was ever counted. */
|
||||
CULTMESH_QUIC_API int32_t cultmesh_quic_debug_peak_calls(void);
|
||||
|
||||
/* How many host calls were counted inside the library when the last
|
||||
* `cultmesh_quic_runtime_close` began its wait, or -1 if no close has begun one
|
||||
* since the hold was armed. This is the number the wait exists for. */
|
||||
CULTMESH_QUIC_API int32_t cultmesh_quic_debug_calls_at_close(void);
|
||||
|
||||
#endif /* CULTMESH_QUIC_DEBUG_ASSERTS */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in a new issue