log_ring: seqlock the records to prevent torn cross-process reads
The lossy MPSC log ring published each record by writing its text and THEN storing the slot's sequence. A consumer that passed the seq==generation check could then read text while a producer 'capacity' generations later overwrote that same slot (it wrote text before bumping seq), yielding a torn line. Diagnostics-only and practically unreachable (it needs the consumer a full ring behind -- ~60k lines/s between two host drains), but a real data race. Make it a proper seqlock: the producer stores seq 0 (in-progress) and fences BEFORE touching the record, then publishes the generation after the text; the consumer copies the record out and re-checks seq, dropping the line if it changed. The ring stays lossy, never torn. Adds log_ring_test (previously zero coverage): a deterministic wrap-drop case plus a threaded torn-read guard (4 producers + a slow consumer on a 32-slot ring) that emits 0 torn lines out of ~300k produced. Closes both the cross-process item and the log_ring coverage gap. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -113,11 +113,7 @@ default** and covers anything the hooked path doesn't.
|
||||
From an in-depth review pass. Each item is fixed test-first (a failing test, then the fix) and lands
|
||||
as its own commit; "verify" items are confirmed real before any change, and dropped if not.
|
||||
|
||||
Cross-process / ABI:
|
||||
- **`log_ring` torn-text window** — verify the MPSC overwrite race; fix or bound it.
|
||||
|
||||
Test coverage:
|
||||
- **`log_ring`** — threaded push/drain + wrap-skip generation test (currently zero coverage).
|
||||
- **Seqlock reader paths** — torn-read retry, odd-sequence skip, attempt-exhaustion → false.
|
||||
- **Version/magic mismatch rejection** — negative test that the hook refuses a bad version.
|
||||
- **Dedicated hook tests** — `focus_spoof`, `vk_hook` (present), `d3d9_hook`.
|
||||
|
||||
Reference in New Issue
Block a user