Skip to content

fix(perftrace): traced click handlers crashed under tracing + freeze classification (v10.12.1) - #48

Merged
tcconnally merged 1 commit into
mainfrom
fix/traced-qt-arity
Jul 15, 2026
Merged

fix(perftrace): traced click handlers crashed under tracing + freeze classification (v10.12.1)#48
tcconnally merged 1 commit into
mainfrom
fix/traced-qt-arity

Conversation

@tcconnally

Copy link
Copy Markdown
Owner

The exerciser's first catch is real — and it's in my instrumentation

All 189 soak invariant violations trace to one mechanism: Qt's clicked signal carries a checked bool; PyQt6 normally drops it by inspecting slot arity, but @traced's bare *args wrapper defeats that inspection. Under tracing (every soak/trace run — never normal launches, which is why buttons always worked for the owner), every traced click handler raised TypeError. The button's checked state toggles before the handler runs, so the handler died and the cache never updated — muted=False vs btn_checked=True, then re-flagged by every subsequent action on the drifted cell. The log shows the smoking gun: TypeError: _toggle_play() takes 1 positional argument but 2 were given.

Fix: cap positional args to the wrapped function's true arity. Regression test: a traced 1-arg method connected to a real QPushButton.clicked with tracing forced on — clicks must run, not raise.

Freeze numbers, honestly re-read

The soak's 85 episodes / ~21 min frozen conflated two things: 43 of its actions were random seeks, each legitimately triggering a demuxer refill at the new offset. Episodes within 5s of a seek now count separately as postseek_refills (own stats field + log tag), so the next soak's freeze count measures only spontaneous starvation — the thing the owner actually experiences. What survives either way: at 8 cells, greg served 48 stalls ≥20s in an hour — the 8-stream concurrency ceiling is the confirmed tranche-2 target.

Suite green (new regression included); version 10.12.1; exe rebuilt.

🤖 Generated with Claude Code

…oad args

The 8-cell soak's invariant checks caught this live on their first
outing: all 189 violations trace to ONE mechanism. Qt's clicked signal
carries a checked bool; PyQt6 normally drops it by inspecting the
slot's arity, but @Traced's bare *args wrapper defeats the inspection —
under tracing (every soak/trace run; never plain launches) EVERY traced
click handler raised TypeError. The button's checked state toggles
BEFORE the handler runs, the handler died, the cached state never
updated: muted=False vs btn_checked=True, re-flagged by each later
action on the drifted cell.

Fix: cap positional args to the wrapped function's true arity
(fn.__code__.co_argcount). Regression test connects a traced 1-arg
method to a real QPushButton.clicked with tracing forced on.

Also: classify freeze episodes. 43 of the soak's actions were random
seeks, each legitimately triggering a demuxer refill — the 85-episode /
21-minute freeze total conflated expected post-seek refills with the
spontaneous cache starvation the owner actually experiences. Episodes
within 5s of a seek now count as postseek_refills (own stats-dump field
+ 'post-seek refill' log tag) so the next soak separates signal from
churn artifact.

Version 10.12.1.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@tcconnally
tcconnally merged commit 8a7e21a into main Jul 15, 2026
2 checks passed
@tcconnally
tcconnally deleted the fix/traced-qt-arity branch July 15, 2026 03:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant