Repository navigation
fix(font): serialize shared FreeType face lifetime - #6282
Conversation
|
Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.
|
|
Linux run of this head, to go with the Windows measurements in the description. Setup: head
So the failures without the fix, and the passes with it, reproduce on Linux/glibc too, not only on Windows/MinGW. The hosted Linux and Windows CI jobs were skipped on this head. By reading: in Not checked: macOS, Clang, the public-API reproduction with a real host font, builds with sanitizers, and the head on its own base (only the merge into Written with AI assistance (Claude Code). I ran the builds and tests above on my machine. AI-assisted: yes |
What
I reproduced a host font-memory leak on main
d92a8dad390af1807cc91622b924252141816a5a. Eight workers use separate guest FontMemory/FontLibrary objects and valid immutable Arial data. All 4,000 public open/metrics/close sequences succeed with correct metrics, but only 3,994 host face finalizers run. At quiescent barriers, the shared FreeType driver lists eight faces instead of the nine still alive. The single-thread control finalizes all 500 faces.State.cppshares one hostFT_Library. Its face creation runs outsidestateMutex, while destruction under that mutex does not synchronize with creation. A lost driver-list node makesFT_Done_Facereturn without destroying the face. FreeType requires a common lock around creation and destruction on a shared library; the pinned header states the same rule at3rdparty/freetype/include/freetype/freetype.h:547-550.I protect cache face creation, replacement and destruction with one mutex. It is declared before the state map so cached faces can still be destroyed during static cleanup. The lock order is
stateMutexthenfaceMutex; loading a face does not acquirestateMutex. Per-face glyph work remains outside this new lock. The shared source fixes the normal, module and native font builds.The regression compiles the production
State.cppand observes actual FreeType face finalizers. It checks single-thread controls, concurrent open/close, replacement, and overlapping creation/destruction in separate processes, plus character mapping and glyph advance. It reuses the existing generated-font builder throughFontFixture.hpp. The public API reproduction separately checks the built runtime library with a real host font; no font binary is added to the repository.I checked the current open PR inventory, including all paths of 21 branches whose API file lists stop at 100, and compared the exact related implementations, tests and discussions. #6019 adds text-code stepping and tests; its GuestFont patch still applies after the fixture extraction. #5209 changes horizontal writing metrics and has a review about console text semantics. #6044 moves the unchanged GuestFont blob and changes test registration/labels. None changes the shared host library or face lifetime. The fixture include uses
tests/FontFixture.hppso its path also resolves after that test relocation.Tested
Captured before/after measurements on the same PC (main
d92a8dad3; counts describe the recorded runs, rather than an average):0xc0000374State.cpprestored to main: all three registered regressions failed. The open/close case finalized 4,009/4,096 faces, creation/destruction finalized 3,448/4,096, and replacement exited with Windows heap corruption0xc0000374. All single-thread controls finalized 128/128. The fixed source was restored and its SHA-256 checked before rebuilding.Limits: no retail title, Linux runtime, console font/threading measurement or claim about console metrics. This fixes the measured host cache lifetime; existing guest-library semantics are unchanged. Full hosted Windows/Linux builds require collaborator dispatch under
CONTRIBUTING.md; skipped jobs are not passes.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)