Commit dd91ea8
authored
test(uffd): add cross-process scaffolding for gated and async ops (#2475)
* test(uffd): add cross-process scaffolding for gated and async ops
Pre-work for the upcoming REMOVE event handling PR. Lands as a runtime
no-op on main: no production code changes, no new UFFD features enabled.
Test-helper additions (all *_test.go):
- testConfig.gated and per-op `async bool`
- operationModeRemove / ServePause / ServeResume / Sleep
- testHandler.servePause / serveResume hooks driven by control pipes
(fd 7/8) into the helper subprocess
- helper subprocess pause/resume goroutine that tears down and restarts
the UFFD serve loop on demand
- executeAll() async path that fans out goroutines and joins on test
context
- expectRemoved + checkDirtiness handling for read/write/remove ordering
- executeRemove via unix.MADV_DONTNEED
- unregister() helper around UFFDIO_UNREGISTER for cleanup
- pageStateEntries() now drains settleRequests then takes the
pageTracker RLock directly so the snapshot stays correct for future
writers (e.g. REMOVE) that don't go through settleRequests
operationModeRemove and the gated/async paths are exercised only by the
follow-up PR; here they are dead code at runtime, kept to minimise the
diff of that PR.
* test(uffd): restore early uffd close cleanup, keep unregister late
* test(uffd): make gated cleanup idempotent to avoid pause-then-exit hang
Codex review caught a deadlock: in GO_GATED mode, handling 'P' replaced
the stop closure with one that drained `exitUffd`, but the deferred
final cleanup still pointed at the original closure. If the helper exited
between 'P' and 'R' (e.g. parent test failure, ctx cancel, SIGUSR1), the
defer ran the original cleanup again and blocked forever on `<-exitUffd`
— the channel had already been drained and the original Serve goroutine
had already exited. The hung helper would in turn hang the parent's
cmd.Wait().
Replace the two-variable (cleanup / stopServe) layout with a single
mutex-guarded `stopFn` that is reset to a no-op after firing, and have
both the gated 'P' handler and the deferred final cleanup go through
the same `stopServe` wrapper. 'R' now just installs a fresh `stopFn`
that drains the new goroutine.
* test(uffd): drop REMOVE-specific bits, keep only gated/async scaffolding
Pull out everything that's not strictly needed for "gated pause/resume +
async ops" so PR T is the smallest possible scaffolding diff and the
follow-up REMOVE PR carries those pieces alongside the production code
that actually needs them:
- helpers_test.go: drop operationModeRemove, executeRemove, expectRemoved
and the REMOVE-aware checkDirtiness branch — none of the PR T tests
call them, and they only become meaningful once UFFD_FEATURE_EVENT_REMOVE
is set in the follow-up.
- fd_helpers_test.go: revert; drop unregister() helper. Without
UFFD_FEATURE_EVENT_REMOVE, MADV_DONTNEED never queues UFFD events, so
munmap doesn't block on un-acked events and there's nothing to
unregister around.
- cross_process_helpers_test.go:
- drop unregister(uffdFd, ...) call in late cleanup (same reason as
above).
- revert pageStateEntries() to the simple settleRequests.Lock pattern;
the rework was forward-looking for a REMOVE handler that doesn't go
through settleRequests and is dead code on main.
- keep cleanup → stopFn/stopServe restructure (mandatory for the
gated tear-down/respawn path) but restore the original
fdExit.SignalExit error handling that the previous version had
silently dropped.
- revert incidental cosmetic reformats (exitUffd placement, defer
multi-line) so the diff is purely additive in the unchanged paths.
* test(uffd): address review comments on cross-process scaffolding
- Guard executeOperation against nil servePause/serveResume hooks when a
non-gated test misuses operationModeServePause/Resume — return a clear
error instead of panicking on a nil function call (cursor + codex).
- Make pageStateEntries() also hold pageTracker.mu.RLock() so the
snapshot stays correct for any future writer that doesn't go through
settleRequests (claude — matches the PR description).
- Make gated 'P' check the gateSyncFile.Write error and propagate via
cancel() so a write failure doesn't leave the parent's servePause
closure blocked indefinitely on Read (claude).
- Make the gated command goroutine reject 'P'-when-paused and
'R'-when-running so a stray or duplicate resume can't leak an
untracked Serve goroutine and break later pauses (codex).
* test(uffd): serialize executeRead under shared RWMutex with executeWrite
Previously executeWrite took h.mutex.Lock() but executeRead held no lock,
so an async write + async read on the same page would race on memoryArea
under go test -race even though the bytes happen to match (data.Slice is
deterministic per offset). Switch h.mutex to sync.RWMutex; reads take
RLock so concurrent reads still trigger UFFD faults in parallel, writes
take Lock so they exclude both other writers and any in-flight reads.
No active test in this PR mixes async read/write yet; this is preemptive
against the upcoming REMOVE PR's matrix tests.1 parent f05d897 commit dd91ea8
2 files changed
Lines changed: 222 additions & 16 deletions
File tree
- packages/orchestrator/pkg/sandbox/uffd/userfaultfd
Lines changed: 156 additions & 13 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| 22 | + | |
22 | 23 | | |
23 | 24 | | |
24 | 25 | | |
| |||
110 | 111 | | |
111 | 112 | | |
112 | 113 | | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
113 | 117 | | |
114 | 118 | | |
115 | 119 | | |
| |||
153 | 157 | | |
154 | 158 | | |
155 | 159 | | |
156 | | - | |
| 160 | + | |
157 | 161 | | |
158 | 162 | | |
159 | 163 | | |
160 | 164 | | |
161 | 165 | | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
162 | 188 | | |
163 | 189 | | |
164 | 190 | | |
| |||
169 | 195 | | |
170 | 196 | | |
171 | 197 | | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
172 | 202 | | |
173 | 203 | | |
174 | 204 | | |
| |||
238 | 268 | | |
239 | 269 | | |
240 | 270 | | |
241 | | - | |
| 271 | + | |
242 | 272 | | |
243 | 273 | | |
244 | 274 | | |
245 | 275 | | |
246 | | - | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
247 | 296 | | |
248 | 297 | | |
249 | 298 | | |
| |||
378 | 427 | | |
379 | 428 | | |
380 | 429 | | |
381 | | - | |
382 | | - | |
383 | | - | |
384 | | - | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
385 | 444 | | |
386 | | - | |
| 445 | + | |
387 | 446 | | |
388 | | - | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
389 | 460 | | |
390 | 461 | | |
391 | 462 | | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
392 | 467 | | |
393 | | - | |
| 468 | + | |
394 | 469 | | |
395 | 470 | | |
396 | | - | |
| 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 | + | |
| 503 | + | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
397 | 535 | | |
398 | 536 | | |
399 | 537 | | |
| |||
423 | 561 | | |
424 | 562 | | |
425 | 563 | | |
426 | | - | |
427 | | - | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
428 | 568 | | |
429 | 569 | | |
430 | 570 | | |
431 | 571 | | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
432 | 575 | | |
433 | 576 | | |
434 | 577 | | |
| |||
Lines changed: 66 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| 6 | + | |
6 | 7 | | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
| 11 | + | |
10 | 12 | | |
11 | 13 | | |
12 | 14 | | |
| |||
26 | 28 | | |
27 | 29 | | |
28 | 30 | | |
| 31 | + | |
| 32 | + | |
29 | 33 | | |
30 | 34 | | |
31 | 35 | | |
32 | 36 | | |
33 | 37 | | |
34 | 38 | | |
35 | 39 | | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
36 | 45 | | |
37 | 46 | | |
38 | 47 | | |
39 | 48 | | |
40 | 49 | | |
41 | 50 | | |
| 51 | + | |
| 52 | + | |
42 | 53 | | |
43 | 54 | | |
44 | 55 | | |
| |||
71 | 82 | | |
72 | 83 | | |
73 | 84 | | |
74 | | - | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
75 | 91 | | |
76 | 92 | | |
77 | 93 | | |
78 | 94 | | |
79 | 95 | | |
| 96 | + | |
| 97 | + | |
80 | 98 | | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
81 | 110 | | |
82 | 111 | | |
83 | 112 | | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
84 | 122 | | |
85 | 123 | | |
86 | 124 | | |
| |||
135 | 173 | | |
136 | 174 | | |
137 | 175 | | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
138 | 192 | | |
139 | 193 | | |
140 | 194 | | |
141 | 195 | | |
142 | 196 | | |
143 | 197 | | |
144 | | - | |
145 | | - | |
146 | 198 | | |
147 | 199 | | |
148 | 200 | | |
149 | 201 | | |
150 | 202 | | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
151 | 213 | | |
152 | 214 | | |
153 | 215 | | |
| |||
165 | 227 | | |
166 | 228 | | |
167 | 229 | | |
| 230 | + | |
168 | 231 | | |
169 | 232 | | |
170 | 233 | | |
| |||
0 commit comments