From 820519cb0c4fb8a1435754e3ae08efde4d21b280 Mon Sep 17 00:00:00 2001 From: Sylpheed RE agent Date: Tue, 25 Aug 2026 10:10:14 +0000 Subject: [PATCH] re: second freeze at ~96s with the inducer on; T74/T75 signature withdrawn Run 2 put the inducer on from flight start and froze ~96s in, against 670s clean with it off -- n=2, contrast sharp, confounder (elapsed mission time) still untouched. Withdraws last iteration's 'T74/T75 move off a semaphore onto an event' as the signature to chase: it does not reproduce. In run 2 they are on XEvent while HEALTHY and stay there. The healthy state varies between instants, so a one-sample-per-state diff cannot separate a freeze transition from ordinary variation -- I read a difference of samples as a difference of states. Reproduces across both: T68 and T69 go from not-waiting to waiting, T69 on a semaphore and T68 on an event both times. And 21 of 24 threads unchanged in run 2 (17 of 24 in run 1), so 'not a whole-emulator stall' now has two independent captures behind it. Next: repeat the capture several times within one healthy run to establish which thread states are stable before reading any frozen diff. --- docs/re/data/waitobj-s02-inducer.txt | 85 +++++++++++++++++++++++++++ docs/re/mission-freeze-resume-spin.md | 48 +++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 docs/re/data/waitobj-s02-inducer.txt diff --git a/docs/re/data/waitobj-s02-inducer.txt b/docs/re/data/waitobj-s02-inducer.txt new file mode 100644 index 0000000..b0e2bdd --- /dev/null +++ b/docs/re/data/waitobj-s02-inducer.txt @@ -0,0 +1,85 @@ +=== healthy: 22 wait frames === + T106 Wait n=1 xe::kernel::XEvent + T105 Wait n=1 xe::kernel::XEvent + T104 Wait n=1 xe::kernel::XEvent + T97 Wait n=1 xe::kernel::XEvent + T96 Wait n=1 xe::kernel::XEvent + T80 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XSemaphore + T79 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XSemaphore + T78 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XSemaphore + T77 Wait n=1 xe::kernel::XEvent + T76 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XTimer + T75 Wait n=1 xe::kernel::XEvent + T74 Wait n=1 xe::kernel::XEvent + T71 Wait n=1 xe::kernel::XEvent + T67 Wait n=1 xe::kernel::XEvent + T66 Wait n=1 xe::kernel::XEvent + T65 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XSemaphore + T64 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XSemaphore + T63 Wait n=1 xe::kernel::XSemaphore + T62 Wait n=1 xe::kernel::XEvent + T61 Wait n=1 xe::kernel::XEvent + T50 Wait n=1 xe::kernel::XEvent + T36 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XEvent + --- objects waited on: + xe::kernel::XEvent 22 + xe::kernel::XSemaphore 6 + xe::kernel::XTimer 1 +=== frozen: 23 wait frames === + T106 Wait n=1 xe::kernel::XEvent + T105 Wait n=1 xe::kernel::XEvent + T104 Wait n=1 xe::kernel::XEvent + T97 Wait n=1 xe::kernel::XEvent + T96 Wait n=1 xe::kernel::XEvent + T80 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XSemaphore + T79 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XSemaphore + T78 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XSemaphore + T77 Wait n=1 xe::kernel::XEvent + T76 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XTimer + T75 Wait n=1 xe::kernel::XEvent + T74 Wait n=1 xe::kernel::XEvent + T71 Wait n=1 xe::kernel::XEvent + T69 Wait n=1 xe::kernel::XSemaphore + T68 Wait n=1 xe::kernel::XEvent + T67 Wait n=1 xe::kernel::XEvent + T66 Wait n=1 xe::kernel::XEvent + T65 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XSemaphore + T64 WaitMultiple n=2 xe::kernel::XEvent, xe::kernel::XSemaphore + T63 Wait n=1 xe::kernel::XSemaphore + T62 Wait n=1 xe::kernel::XEvent + T61 Wait n=1 xe::kernel::XEvent + T50 Wait n=1 xe::kernel::XEvent + --- objects waited on: + xe::kernel::XEvent 21 + xe::kernel::XSemaphore 7 + xe::kernel::XTimer 1 +=== healthy -> frozen === + xe::kernel::XEvent 22 -> 21 CHANGED + xe::kernel::XSemaphore 6 -> 7 CHANGED + xe::kernel::XTimer 1 -> 1 +=== per-thread healthy -> frozen === + thread healthy frozen + T106 Wait(XEvent) Wait(XEvent) + T105 Wait(XEvent) Wait(XEvent) + T104 Wait(XEvent) Wait(XEvent) + T97 Wait(XEvent) Wait(XEvent) + T96 Wait(XEvent) Wait(XEvent) + T80 WaitMultiple(XEvent,XSemaphore) WaitMultiple(XEvent,XSemaphore) + T79 WaitMultiple(XEvent,XSemaphore) WaitMultiple(XEvent,XSemaphore) + T78 WaitMultiple(XEvent,XSemaphore) WaitMultiple(XEvent,XSemaphore) + T77 Wait(XEvent) Wait(XEvent) + T76 WaitMultiple(XEvent,XTimer) WaitMultiple(XEvent,XTimer) + T75 Wait(XEvent) Wait(XEvent) + T74 Wait(XEvent) Wait(XEvent) + T71 Wait(XEvent) Wait(XEvent) + T69 -- Wait(XSemaphore) <-- CHANGED + T68 -- Wait(XEvent) <-- CHANGED + T67 Wait(XEvent) Wait(XEvent) + T66 Wait(XEvent) Wait(XEvent) + T65 WaitMultiple(XEvent,XSemaphore) WaitMultiple(XEvent,XSemaphore) + T64 WaitMultiple(XEvent,XSemaphore) WaitMultiple(XEvent,XSemaphore) + T63 Wait(XSemaphore) Wait(XSemaphore) + T62 Wait(XEvent) Wait(XEvent) + T61 Wait(XEvent) Wait(XEvent) + T50 Wait(XEvent) Wait(XEvent) + T36 WaitMultiple(XEvent,XEvent) -- <-- CHANGED diff --git a/docs/re/mission-freeze-resume-spin.md b/docs/re/mission-freeze-resume-spin.md index 4ff5a01..4eaf26f 100644 --- a/docs/re/mission-freeze-resume-spin.md +++ b/docs/re/mission-freeze-resume-spin.md @@ -1042,3 +1042,51 @@ unpacking and comparing every word in Python takes **~4.2 s per pass**. **The experiment that would settle it:** alternate inducer-on and inducer-off windows within one run, several runs, and compare freeze rate per unit of *mission* time. Cheap now that `watch` is event-driven. + +## ✅ 2026-08-25 — second freeze, and it REFUTES the signature I named + +Ran the control's opposite: inducer **on from the moment flight begins** +(`freeze_waitobj.sh run` with `SYLPH_INDUCE=1`, launched detached so no `timeout` +can kill the process group). + +| run | inducer | outcome | +|---|---|---| +| 1 | off for 670 s, then on | clean 670 s, then **frozen 54 s** after it started | +| 2 | **on from flight start** (10:07:20) | **frozen ~96 s later** (10:08:56) | + +Both freezes land inside the 27–255 s band the old heavy-probe runs froze in, +and the one long clean stretch is the only window with no inducer. **n=2, and the +contrast is now sharp** — but it is still two runs, the confounder (elapsed +mission time) is untouched, and the alternating-window test is what would settle +it. + +### 🔴 WITHDRAWN: "T74/T75 move off a semaphore onto an event" + +Last iteration I called that "the pair to chase — the only threads that change +what *kind* of object they wait for". **It does not reproduce.** In run 2, T74 +and T75 sit on `Wait(XEvent)` in the *healthy* capture and stay there when +frozen. + +The reason is a sampling error I should have caught: the **healthy** state is not +fixed either. Run 1 happened to catch T74/T75 on a semaphore; run 2 caught them +on an event. A one-sample-per-state comparison cannot tell a freeze transition +from ordinary variation between two instants, and I read a difference of samples +as a difference of states. + +### ✅ What DOES reproduce across both freezes + +**T68 and T69 go from not-waiting to waiting, in both runs** — and T69 lands on +an `XSemaphore` both times, T68 on an `XEvent` both times. Everything else is +run-specific: run 1 also parked T105/T67, run 2 instead dropped T36 out of its +wait. + +And in both runs the great majority of threads are untouched — 17 of 24 in run 1, +**21 of 24** in run 2 — which keeps the one structural claim that has now +survived two independent captures: **the freeze is not a whole-emulator stall.** + +Data: `data/waitobj-s02.txt` (run 1), `data/waitobj-s02-inducer.txt` (run 2). + +**Still open:** whether T68/T69 are cause or consequence; one sample per state +cannot say. The fix for the error above applies here too — **repeat the capture +several times within a single healthy run** to learn which thread states are +stable before reading any frozen diff as meaningful.