| … | … | @@ -2509,6 +2509,36 @@ SessionState's truncate / reorg / named-session machinery. |
| 2509 | 2509 | - one mixed-mode scenario (COMPAT ↔ SMALL_WANTS) for interop. |
| 2510 | 2510 | - TRAP: the flag is module-global in JS and process-global in keetd. Set it before any |
| 2511 | 2511 | replicator exists, and reset it between tests. |
| 2512 | - **DONE 2026-10-04** (keetd fcb14b6 + 1d0b224). |
| 2513 | - Vectors: COMPAT 10126/10126 (the file is byte-identical to before), SMALL 10130/10130. |
| 2514 | Test-first: red on `WANT_BATCH`, then on the any ranges, then green. |
| 2515 | - Pipe s19 / s19c (a sparse uploader) green: keetd sends JS's exact want / unwant |
| 2516 | sequence in both modes. |
| 2517 | - **Drill `m5g4e1`: 8/8 red**, both controls ok. |
| 2518 | - **REAL BUG found (fcb14b6): `Attachable::gc()` read `wants` after `unref()` had |
| 2519 | dropped the LAST owner.** `_seeks`, `_ranges`, `_upgrade` and the block tracker own |
| 2520 | their requests; JS's garbage collector keeps the object alive. The symptom: a timed-out |
| 2521 | seek's any want was never unwanted. `unref()` now returns the owner it released, and |
| 2522 | `gc()` holds it until it returns. |
| 2523 | - **Upstream COMPAT quirk:** the any want CHURNS. `addAnyRange` stores the ROUNDED range, |
| 2524 | `_maybeWantAnyRange` compares it with the UNROUNDED span, so every `_requestSeek` |
| 2525 | pass sends unwant + want. The uploader answers each want with a bitfield of the whole |
| 2526 | range: 2^21 bits, 256 KB. In 1 s that was ~1.7k round trips JS↔JS and ~17k keetd↔JS |
| 2527 | (the downloader's decode speed sets the rate). The count is timing, so it is not |
| 2528 | gated; s19c has no hole-seek, and COMPAT's any rounding is gated by the vectors. |
| 2529 | - **Harness fixes:** |
| 2530 | - configs past MAX_ARG_STRLEN go through a file (exec failed with E2BIG, silently); |
| 2531 | - an exec failure reports itself; |
| 2532 | - a stdout line that is not a JSON object is never a report; |
| 2533 | - a missing received report is null, never `[]` (that once read as "JS sent nothing"). |
| 2534 | - **ctest:** |
| 2535 | - m3c_pipe is one test per scenario: one SCENARIOS table drives the default run, |
| 2536 | `M3C_ONLY` and CMake, and an unknown name fails; |
| 2537 | - JS↔JS controls are cached in `build/m3c-controls`, keyed by script plus a |
| 2538 | fingerprint of peer.js, child.h and the JS modules; |
| 2539 | - m5f_blobs_monitor runs serial: its speeds are real-time, and late timers under |
| 2540 | `-j16` failed its JS↔JS reference check. |
| 2541 | - `ctest -j16`: 377 s → 213 s cold, 158 s warm. |
| 2512 | 2542 | - **4e-2, extensions + `inspect`.** |
| 2513 | 2543 | - Per-session `extensions` (re-registering replaces the handlers, encoding and |
| 2514 | 2544 | session). |