Commit 0490606
committed
fix(mesh-conn): converge ICE auth-race with asymmetric retry + supersede grace
The bug: on near-simultaneous restart (the normal startup case)
mesh-conn's pollLoop superseded each peer's in-flight handshake the
moment fresher peer auth arrived; each abort's retry rebuilt the
ice.Agent (mandatory — pion's Restart() doesn't support re-Dial; see
peerSession docstring), republished a fresh local auth, and triggered
the peer's symmetric supersession. Both sides flapped indefinitely.
Observed live on 2026-05-13 as multiple peer pairs stuck in the
"fresh auth supersedes consumed → ice: connecting canceled by caller
→ retrying in 5s → Closed" loop for 7+ minutes; replica
pg_basebackup never started.
Two coupled changes:
1. Asymmetric retry back-off in runPeerLink, keyed on peer-id lex
order: lex-smaller side waits 2 s, larger waits 5 s. The 3 s gap
guarantees one side's retry is the authoritative auth publisher
per cycle; by the time the slower side wakes up, the faster side
is in "wait for auth" (consumedAuth=zero) and the supersession
check short-circuits.
2. A 3 s grace window on the supersession check in pollLoop: an
in-flight handshake is only allowed to be aborted by a fresh peer
auth if it has been running long enough that the auth credibly
signals a peer-side credential roll rather than early-race noise.
On loopback host candidates the legitimate handshake completes in
~60 ms — well inside the grace — so any forge / re-emit landing
in that window is ignored.
Either fix alone is insufficient — measured against the regression
test, asymmetric back-off alone keeps flapping (the supersede still
fires on the in-flight peer mid-Checking before its retry even
sleeps), and a grace window alone leaves a race where the symmetric
retry republishes auth in close-enough succession that the broken
fallback path can still re-enter. Composed, the AFTER measurement
is 50/50 passes in 3.5 s total.
Regression test (mesh-conn/main_test.go::TestAuthRaceConvergence):
- in-process harness with two Mesh instances + an inlined /publish +
/poll broker (matches signaling/main.go's wire format),
- forges fresh peer auth in a 20-shot burst gated on a new
onAttemptStarted Mesh hook (fires the instant consumedAuth gets
set inside dialICE) so the forge reliably lands in the in-flight
window the supersede check guards,
- asserts both peers reach "link up" within 30 s.
Numbers: BEFORE the fix the regression test fails 32 / 1-pass / 33
trials with the original single-shot forge variant (the 1 pass was
the link-came-up-before-forge race that motivated the new
attemptStarted hook); on the sustained-forge + hook variant the
BEFORE failure rate is 100 %. AFTER the fix: 50 / 50 passes in
3.5 s total.
Refactor of pollLoop / runPeerLink / dialAndPump / dialICE into
*Mesh methods (instance-scoped sessions, ctx-bounded shutdown,
onLinkUp + onAttemptStarted hooks) landed in the prior commit; this
commit is the actual fix + the strengthened test.1 parent fa274ef commit 0490606
3 files changed
Lines changed: 144 additions & 57 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
116 | 116 | | |
117 | 117 | | |
118 | 118 | | |
119 | | - | |
120 | | - | |
121 | | - | |
122 | | - | |
123 | | - | |
124 | | - | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
125 | 126 | | |
126 | 127 | | |
127 | 128 | | |
| |||
145 | 146 | | |
146 | 147 | | |
147 | 148 | | |
148 | | - | |
149 | | - | |
150 | | - | |
151 | | - | |
152 | | - | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
153 | 155 | | |
154 | 156 | | |
155 | 157 | | |
156 | 158 | | |
157 | 159 | | |
158 | 160 | | |
159 | 161 | | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
160 | 168 | | |
161 | 169 | | |
162 | 170 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
397 | 397 | | |
398 | 398 | | |
399 | 399 | | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
400 | 408 | | |
401 | 409 | | |
402 | 410 | | |
| |||
446 | 454 | | |
447 | 455 | | |
448 | 456 | | |
| 457 | + | |
449 | 458 | | |
450 | | - | |
451 | | - | |
| 459 | + | |
| 460 | + | |
452 | 461 | | |
453 | 462 | | |
454 | 463 | | |
| |||
458 | 467 | | |
459 | 468 | | |
460 | 469 | | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
461 | 503 | | |
462 | 504 | | |
463 | 505 | | |
| |||
511 | 553 | | |
512 | 554 | | |
513 | 555 | | |
| 556 | + | |
514 | 557 | | |
515 | 558 | | |
516 | 559 | | |
| |||
1012 | 1055 | | |
1013 | 1056 | | |
1014 | 1057 | | |
| 1058 | + | |
1015 | 1059 | | |
1016 | 1060 | | |
1017 | 1061 | | |
1018 | 1062 | | |
| 1063 | + | |
| 1064 | + | |
| 1065 | + | |
| 1066 | + | |
| 1067 | + | |
| 1068 | + | |
| 1069 | + | |
| 1070 | + | |
| 1071 | + | |
| 1072 | + | |
| 1073 | + | |
| 1074 | + | |
| 1075 | + | |
| 1076 | + | |
| 1077 | + | |
| 1078 | + | |
| 1079 | + | |
| 1080 | + | |
| 1081 | + | |
1019 | 1082 | | |
1020 | 1083 | | |
1021 | 1084 | | |
| |||
1164 | 1227 | | |
1165 | 1228 | | |
1166 | 1229 | | |
1167 | | - | |
| 1230 | + | |
| 1231 | + | |
1168 | 1232 | | |
1169 | 1233 | | |
| 1234 | + | |
1170 | 1235 | | |
| 1236 | + | |
| 1237 | + | |
| 1238 | + | |
1171 | 1239 | | |
1172 | 1240 | | |
1173 | 1241 | | |
| |||
1292 | 1360 | | |
1293 | 1361 | | |
1294 | 1362 | | |
1295 | | - | |
1296 | | - | |
| 1363 | + | |
| 1364 | + | |
| 1365 | + | |
| 1366 | + | |
| 1367 | + | |
1297 | 1368 | | |
1298 | 1369 | | |
1299 | 1370 | | |
| |||
1303 | 1374 | | |
1304 | 1375 | | |
1305 | 1376 | | |
1306 | | - | |
1307 | | - | |
1308 | | - | |
| 1377 | + | |
| 1378 | + | |
| 1379 | + | |
| 1380 | + | |
| 1381 | + | |
| 1382 | + | |
| 1383 | + | |
| 1384 | + | |
| 1385 | + | |
1309 | 1386 | | |
1310 | 1387 | | |
1311 | 1388 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | | - | |
7 | 6 | | |
8 | 7 | | |
9 | 8 | | |
| |||
48 | 47 | | |
49 | 48 | | |
50 | 49 | | |
51 | | - | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
58 | | - | |
59 | | - | |
60 | | - | |
61 | | - | |
62 | | - | |
63 | | - | |
64 | | - | |
65 | | - | |
66 | | - | |
67 | | - | |
68 | | - | |
69 | | - | |
70 | | - | |
71 | 50 | | |
72 | 51 | | |
73 | 52 | | |
| |||
104 | 83 | | |
105 | 84 | | |
106 | 85 | | |
107 | | - | |
108 | | - | |
109 | | - | |
110 | | - | |
111 | | - | |
112 | | - | |
113 | | - | |
114 | | - | |
115 | | - | |
116 | | - | |
117 | | - | |
118 | | - | |
119 | | - | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
120 | 99 | | |
121 | 100 | | |
122 | | - | |
123 | | - | |
124 | | - | |
125 | | - | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
126 | 128 | | |
127 | 129 | | |
128 | 130 | | |
| |||
0 commit comments