Repository navigation
Conversation
…inux) The window turns grey and stops answering when a chat draws an emoji on a system whose colour emoji font is the COLRv1 format (Fedora 44, newer Ubuntu). The WebKitGTK inside the AppImage paints that format through Skia, and its colrv1_configure_skpaint reads past the end of a gradient's colour-stop list; the library is built with libstdc++ range checks, so the read is an abort() and WebKitWebProcess is gone. The window process is still there, so the shell sees nothing wrong and the page is never reloaded: the person has a grey box and no message. It repeats on every start that restores a chat with an emoji in it. The window process now points fontconfig at a file of its own that rejects only the COLRv1 faces and prefers the outline "Noto Emoji", so emoji arrive as outlines instead of colour. It pulls in /etc/fonts/fonts.conf first, so every other font resolves exactly as before, and it is set only in the window process: the host, the engine and the agent keep the fonts the person chose. The file is written under the app's own data folder, atomically, and only when a COLRv1 font is actually installed, so a machine without one is untouched. FONTCONFIG_FILE stays the person's own if they set it, and STRATA_FONT_CONFIG=off turns this off. The three font variables go into the window's crash report beside the other graphics settings, because which font file is in use is the whole question here. Checked on Fedora 44 with the font that fails: fontconfig lists 895 fonts with the file and 896 without, the one difference being Noto-COLRv1.ttf; "Noto Color Emoji", "emoji" and the ordinary text families all resolve, with no fontconfig warnings. Four unit tests cover the file's contents and nesting, the opt-outs, the scan, and the write-and-refresh. cargo clippy is clean for the new module. Not checked: the real window on a real desktop, and the older SIGSEGV crashes on the JITWorker thread, which are a separate fault.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
On Linux, the app window turns grey and stops answering when a chat draws an emoji, on any system whose colour emoji font is the COLRv1 format (Fedora 44 and newer Ubuntu ship it as the default). The window log says:
The WebKitGTK inside the AppImage paints COLRv1 through Skia, and
colrv1_configure_skpaintindexes past the end of a gradient's colour-stop vector. The library is built with_GLIBCXX_ASSERTIONS, so that read becomesabort()andWebKitWebProcessdies.What makes it bad rather than merely wrong is the recovery: the shell only watches the window process, and that process can stay alive when its web process dies. Nothing is then logged, nothing reloads, no crash log is written, and the person is left with a grey box and no message. A chat that contains an emoji reproduces it on every start that restores that chat.
The approach
Keep the one font family that cannot be drawn away from the window process — nothing else.
/etc/fonts/fonts.conffirst, so every other font resolves exactly as it does today, then rejects*/Noto-COLRv1.ttfand*/NotoSansCOLRv1-Regular.ttfinside<selectfont>and prefers the outlineNoto Emojifor theNoto Color Emojifamily. Emoji arrive as outlines instead of in colour.FONTCONFIG_FILEalready set stays untouched (the person's own choice wins).STRATA_FONT_CONFIG=offturns this off;STRATA_FONT_CONFIG=/path/to/fonts.confuses a file of theirs.The bitmap (
CBDT) and outline faces are not rejected — they draw fine, and hiding them would leave a tofu box instead of an emoji.Validation
Passed
cargo test --releasein the desktop shell: the 4 new tests infontguard.rspass — the file's contents and its<selectfont>nesting, that each reject sits inside it and that no placeholder is left unexpanded, both opt-outs and a custom file, the shallow scan (the bitmap and outline faces alone must not trigger it), and write-once-plus-refresh with no temporary left behind.cargo clippy --release: no findings in the new module. (It reports 8needless_borrowin the Linux drag-drop code, onedoc list item without indentationatmain.rs:22from commit322790af, and one dead function inshell.rs; all pre-existing, all left alone.)GLIBC_2.34, the same floor as the shippedstrata-desktop, and carries the sameRUNPATH=$ORIGIN/../lib, so it is a drop-in and no narrower than today.fc-listreturns 895 fonts with it and 896 without — the single difference isNoto-COLRv1.ttf.Noto Color Emojiandemojiresolve toNotoEmoji-Regular.ttf;sans-serif,monospace,Segoe UI,Noto Sans,DejaVu Sans MonoandCourier Newresolve exactly as before. Zero fontconfig warnings.WebKitWebProcessit forks carriesFONTCONFIG_FILE=…/fonts/fonts-no-colrv1.confin its own environment; the official 0.2.7 binary's web process has the variable unset. So the guard runs, runs before WebKit forks its renderer, and reaches the process that does the drawing. Both windows stayed up and served the page: no regression from the change.Failed (pre-existing, unchanged by this pull)
desktoplog::tests::a_failed_start_is_explained_in_plain_words_and_written_to_a_crash_fileasserts the literal"0.2.0"while the crate is0.2.7. It fails identically on pristineupstream/mainin the same container with these files removed. One-line fix, left out because it is not this problem.Not run
colrv1_configure_skpaint— which exists only in the COLRv1 path and is the onlycolrv1_*symbol in the library — plus the log lines and coredumps from the real app, and the same assertion and the same fontconfig workaround reported independently by other AppImage projects on Fedora 44. It is not a controlled before/after.#[cfg(target_os = "linux")].SIGSEGVcrashes on aJITWorkerthread seen on the reporting machine. A different fault, not addressed here — see limits.Limits
colrv1_configure_skpaint, and colour emoji in the window become outline emoji. The real fix belongs upstream in WebKitGTK/Skia.colrv1. A COLRv1 colour font under another name would still get through.WebKitWebView::connect_web_process_terminatedis available in the pinnedwebkit2gtk 2.0.2and is used nowhere in the shell. That deserves its own issue; a workaround for one renderer fault should not pretend the recovery path is fine.Reproduce
fc-match "Noto Color Emoji"returnsNoto-COLRv1.ttf).~/.local/share/strata/logs/desktop-*.logshows thecolrv1_configure_skpaintassertion;coredumpctlshowsWebKitWebProcesswithSIGABRT.Workaround for anyone hitting it before this lands: point
FONTCONFIG_FILEat a file that includes/etc/fonts/fonts.confand rejects*/Noto-COLRv1.ttfinside<selectfont>.