Commit d7f4546
committed
fix(realtime): repair hub shutdown deadlock and WaitGroup misuse
internal/realtime has timed out at 3m under -race on seven CI runs since
2026-08-21 (#212), on PRs that touch no Go code. Three defects, all in
the Hub start/stop lifecycle:
1. The writer goroutine's cleanup sent on h.unregister unconditionally
after a racy h.stopped pre-check. Stop() can flip that flag and the
run loop can return between the load and the send, leaving the writer
blocked forever on a channel nobody drains — so writerWg.Wait() never
returns and shutdown wedges. This is the 3m hang. Select on stopCh and
close the client directly instead; the existing CAS guard keeps that
safe against the run loop's own stop-path close. HandleWebSocket's
h.register send had the same shape and gets the same treatment.
2. Run() called h.wg.Add(1) from inside the goroutine while Stop() called
h.wg.Wait() — an Add from zero concurrent with Wait. Stop() could
return before the loop had started, leaving it running afterwards.
The count is now taken in NewHub and consumed by whichever of Run or
Stop claims runOwner first, so Add always happens-before Wait and a
hub that is never Run still stops cleanly.
3. HandleWebSocket called h.writerWg.Add(1) with no ordering against
Stop()'s writerWg.Wait(), same misuse. Writer slots are now reserved
through admitWriter() under lifecycleMu, which refuses once Stop has
begun, so every Add is ordered before the Wait.
The dead h.stopped flag is removed with its last reader.
TestStopDoesNotDeadlockAgainstChurn drives connect/disconnect churn
against a concurrent Stop() and fails on the unpatched hub (verified:
DATA RACE) while passing on the fix. Also run: 20x internal/realtime
under -race with GOMAXPROCS=2 (340 tests, green) and the full suite
(1527 tests, 30 packages, green).1 parent db7ac81 commit d7f4546
2 files changed
Lines changed: 147 additions & 14 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
91 | 91 | | |
92 | 92 | | |
93 | 93 | | |
94 | | - | |
95 | | - | |
96 | | - | |
97 | | - | |
98 | | - | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
99 | 109 | | |
100 | 110 | | |
101 | 111 | | |
| |||
150 | 160 | | |
151 | 161 | | |
152 | 162 | | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
153 | 166 | | |
154 | 167 | | |
155 | 168 | | |
156 | 169 | | |
157 | 170 | | |
158 | | - | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
159 | 176 | | |
160 | 177 | | |
161 | 178 | | |
| |||
388 | 405 | | |
389 | 406 | | |
390 | 407 | | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
391 | 421 | | |
392 | 422 | | |
393 | | - | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
394 | 427 | | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
395 | 433 | | |
396 | 434 | | |
397 | 435 | | |
| |||
448 | 486 | | |
449 | 487 | | |
450 | 488 | | |
451 | | - | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
452 | 509 | | |
453 | 510 | | |
454 | | - | |
455 | 511 | | |
456 | 512 | | |
457 | 513 | | |
458 | 514 | | |
459 | 515 | | |
460 | 516 | | |
461 | 517 | | |
462 | | - | |
463 | | - | |
464 | | - | |
465 | | - | |
466 | | - | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
467 | 530 | | |
468 | 531 | | |
469 | 532 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
0 commit comments