Skip to content

Log crashes to the diagnostics file; decode each MXP picture once - #68

Merged
HarryCordewener merged 3 commits into
mainfrom
claude/project-thread-ofes9o
Oct 26, 2026
Merged

HarryCordewener merged 3 commits into
mainfrom
claude/project-thread-ofes9o

Conversation

@HarryCordewener

@HarryCordewener HarryCordewener commented Oct 26, 2026 •

Copy link
Copy Markdown
Member

Requested by Grave · project thread

Two changes from the same investigation.

Crashes reach client-diagnostics-*.log

A crash in the window left nothing in client-diagnostics-*.log. The only record was in Windows Event Viewer and %LOCALAPPDATA%\CrashDumps. Three gaps are closed, in RunLive (shared by both hosts) and in SharpMUTermApp:

  • SharpConsoleUI's own log is now forwarded, Warning and up (ClientDiagnostics.Forward). The framework catches whatever its main loop and queued UI actions (EnqueueOnUIThread, behind our OnUiThread) throw, then logs it to a LogService that writes nowhere unless SHARPCONSOLEUI_DEBUG_LOG is set. When the loop dies it returns 1 and prints the stack to a console, which the window doesn't have.
  • Unhandled and unobserved exceptions are recorded while RunLive runs (ClientDiagnostics.RecordUnhandled). This covers AppDomain.UnhandledException, which also catches an exception escaping Avalonia's UI thread, and TaskScheduler.UnobservedTaskException. Neither is marked handled. The file sink is unbuffered, so the line is on disk before the process ends.
  • An exception escaping Run is logged before it reaches MainWindow's catch, which only writes to Console.Error. A non-zero exit code is logged too.

The crashes that prompted this were native faults on one machine and would not have reached any of these hooks. The same WebP decodes identically 680 times on Linux x64 with the same ImageSharp and runtime, and other programs on that machine crash with the same codes.

Each MXP picture is fetched and decoded once per session

InlineImageHost's cache held finished rows, keyed by presentation, pane width, box and URL. A room picture re-sent on every look was therefore fetched and decoded again after any resize, split or sidebar change. Looks that arrived before the first fetch returned each started their own fetch. Decoding is the expensive half: a desktop-sized WebP costs tens of milliseconds of SIMD work.

  • Decoded pictures are now kept per URL, with a 64 MB pixel budget, least recently used evicted first. A picture larger than the whole budget is used once and not kept.
  • A fetch already under way is shared.
  • A failed fetch is not remembered, so the next mention tries again.
  • The row cache stays, so a repeat at the same size is still not rescaled or re-transmitted under Kitty.

Tests

  • CrashLoggingTests (Tui): framework errors are forwarded with their exception, framework debug/info output is not, nothing is forwarded after disposal, and a live app forwards its framework's log.
  • InlineImageCacheTests (Tui): a second width doesn't refetch, three looks during one fetch share it, a failure is retried, and the budget keeps or drops a picture correctly.
  • Tui (1965) and Avalonia (191) suites are green. The solution builds with no warnings.

🤖 Generated with Claude Code

https://claude.ai/code/session_011SqUn5K4cB6cU9zp3HmVmF

The window has no console, so an exception that ended the client loop, or
escaped every thread, left no trace in client-diagnostics-*.log. The
framework's log (where it reports what its loop and queued UI actions
threw) is now forwarded from Warning up, and unhandled and unobserved
exceptions are recorded for the life of RunLive, in both hosts.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_011SqUn5K4cB6cU9zp3HmVmF
@HarryCordewener HarryCordewener self-assigned this Oct 26, 2026
@coderabbitai

coderabbitai Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Caution

Review failed

The pull request is closed.

Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

The row cache was keyed by pane width, so a picture re-sent on every
look was fetched and decoded again after any resize, split or sidebar
change, and looks landing before the first fetch returned each started
their own. Decoded pictures are now kept per URL (64 MB, least recently
used first) and a fetch under way is shared.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_011SqUn5K4cB6cU9zp3HmVmF
@HarryCordewener HarryCordewener changed the title Write crashes to the client diagnostics file Log crashes to the diagnostics file; decode each MXP picture once Oct 26, 2026
@HarryCordewener
HarryCordewener marked this pull request as ready for review October 26, 2026 19:47
@HarryCordewener
HarryCordewener merged commit 8e581b3 into main Oct 26, 2026
3 of 4 checks passed
@HarryCordewener
HarryCordewener deleted the claude/project-thread-ofes9o branch October 26, 2026 19:47
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.

2 participants