Skip to content

Intermittent crash on startup with zh_TW/zh_CN locale and empty workspace (libSkiaSharp TTC font bug) #2551

Description

@JC-Chung

工作區沒有任何存放庫且語言為中文時有機會打不開 `SourceGit
早上/下午能持續重現問題,但像發文前的現在又都能正常開啟
有試過問題發生時中文以外都能正常開啟

另外 Locale 沒有對應語言時 UI 會沒顯示任何文字,是否 fallbacken_US 會比較好


Steps to Reproduce

  1. Set Locale to zh_TW or zh_CN in preference.json
  2. Ensure Workspaces[0].Repositories is an empty array []
  3. Launch SourceGit.exe

Expected: Application opens normally.

Actual: The process appears briefly in Task Manager and immediately disappears. No crash log is generated. The behavior is intermittent — rapid repeated launches occasionally succeed. Deleting data/process.lock before launching does not reliably fix the issue. The problem does not occur with any other locale.


Environment

  • SourceGit: v2026.15 (7149a8d70c), and intermittently in v2026.14 (see below)
  • Build: Official release (Native AOT, .NET 10.0.301, win-x64)
  • Avalonia: 11.3.18 → SkiaSharp 2.88.9 (Skia m88)
  • OS: Windows

Affected Commits in v2026.14

The issue was observed between:

  • 34f4a7c6f2refactor: use * instead *.* to choose file without specified extensions (2026-07-02)
  • 222cd80272ux: use Ctrl/⌘+W to close sub-windows (2026-07-06)

The crash was not reproduced after 7327ccd266 (localization: update Chinese translations, 2026-07-06), though this may simply be due to the intermittent nature of the bug. It reappeared in v2026.15 (7149a8d70c).


* Guess

Root Cause

Analyzed via x64dbg on the official release binary.

The crash occurs on the Avalonia render thread — not the main thread — which is why .NET's UnhandledException handler is never triggered and no crash log is produced.

Crash location: libSkiaSharp.dll offset 0x4ABE05
Instruction: mov rax, qword ptr ds:[rcx] (rcx = 0x0)
Exception: EXCEPTION_ACCESS_VIOLATION (last-chance)

Call stack:

  1. libSkiaSharp.dll — TTC font parsing (crash)
  2. SourceGit.exe — P/Invoke wrapper for sk_stream_read
  3. SourceGit.exe — Avalonia render/layout traversal

When Avalonia's render thread calls SKFontManager.MatchCharacter() to find a font for Chinese characters, it goes through the DirectWrite font manager (SkFontMgr_win_dw.cpp). On a cache miss, DirectWrite performs lazy loading of TTC font data. During this, an internal function sets the stream pointer to null, but the caller still tries to use it — null pointer dereference.

Why only zh_TW/zh_CN: Chinese system fonts (mingliu.ttc, msjh.ttc, etc.) are almost exclusively TTC format. Other locales use single TTF files and don't hit this path.

Why intermittent: TTC fonts have a cache. Cache hits skip full parsing (no crash); cache misses trigger the full TTC parsing path (crash).

Why only with empty repositories: When repositories are open, other UI elements appear to pre-warm the font cache before the problematic render path is reached. With only the Welcome page shown, the cache miss occurs at a critical moment.


SkiaSharp / Skia Context

Avalonia SkiaSharp Skia milestone
11.3.18 (current) 2.88.9 m88
12.0.4 / 12.1.0 3.119.4 m119

The DirectWrite font manager was refactored multiple times between m88 and m119. Upgrading to Avalonia 12.x would move to SkiaSharp 3.119.4 and likely fix this crash.

Note: SourceGit previously upgraded to Avalonia 12.0.4 (a0d51fee) but downgraded back to 11.3.18 (8477bdd0) due to TextEditor performance and memory issues.


Questions

  1. Has the TextEditor performance/memory issue that caused the downgrade from Avalonia 12.0.4 been resolved in Avalonia 12.1.0? Upgrading to 12.x would likely fix this crash as a side effect.
  2. Is there a cleaner official way to pre-warm the font cache during startup (e.g., in BuildAvaloniaApp())?

Metadata

Metadata

Assignees

Labels

need-more-infoExtra information or replay is needed

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions