mirror of
https://github.com/PerpetualSoftware/pad.git
synced 2026-09-23 02:53:31 +00:00
7e20e29754
Aiming a round at the previous round's fixes paid, which is the second time this week that has been the sharpest angle available. 1. The lifecycle fix guarded the FIELDS and not the OPERATION. Stop cleared started, released the lock, and only then cancelled and waited — so a Start racing into that window installed a fresh loop the in-flight Stop neither cancelled nor could end, while both shared one WaitGroup. Start and Stop are now serialized end to end by a dedicated lifecycleMu, deliberately not the state mutex, because probe() takes that one on the goroutine Stop waits for. 2. The gauge fix made the callback reorderable. It captured the total under the lock and fired outside it, so one admission could capture 1, a concurrent one capture 2, and the stale 1 land last — leaving pad_stream_connections_active permanently BELOW the real total, which reads to an operator as spare capacity that is not there. The callback now reads the total at notify time under a notify mutex, so whichever fires last also read last and the gauge converges. Both tests are concurrent, because the sequential ones structurally could not see either defect — round 10 said so and it was right. The gauge test needed a second pass to become an instrument. The first version SURVIVED five runs against the broken build: the reorder window is real but too narrow to hit reliably, so the test could not fail and would have shipped as coverage that proves nothing. It now widens the window deliberately with a sleep inside the observer, and the broken build fails it by name (gauge = 9 against a true total of 8). The lifecycle test catches its mutation as a data race plus a failure. Claude-Session: https://claude.ai/code/session_01JVDBKbgn3Xt7ndW1YoYd8X