@@ -63,12 +63,20 @@ FontManager::FontManager() {
6363std::vector<std::unique_ptr<xlFont>> FontManager::fonts;
6464bool FontManager::initialized = false ;
6565std::vector<std::string> FontManager::names;
66+ std::once_flag FontManager::initOnceFlag;
67+ std::once_flag FontManager::namesOnceFlag;
6668
6769FontManager::~FontManager () {
6870}
6971
7072void FontManager::init () {
71- if (!initialized) {
73+ // TextEffect::RenderXLText calls this from frame-parallel render worker
74+ // threads, so the one-time population of the static fonts/names vectors
75+ // below must be serialized rather than gated by a plain bool check -
76+ // concurrent first calls used to race on the same push_back'd vectors,
77+ // corrupting them (xLightsSequencer/xLights headless-render nondeterminism
78+ // investigation, ACCESS_VIOLATION inside FontManager::init under load).
79+ std::call_once (initOnceFlag, []() {
7280 get_font_names (); // ensure names are populated
7381
7482 fonts.push_back (std::make_unique<xlFont>(font_5_5x5_thin_system_png, sizeof (font_5_5x5_thin_system_png)));
@@ -97,11 +105,11 @@ void FontManager::init() {
97105 }
98106
99107 initialized = true ;
100- }
108+ });
101109}
102110
103111const std::vector<std::string>& FontManager::get_font_names () {
104- if (names. empty () ) {
112+ std::call_once (namesOnceFlag, []( ) {
105113 names.push_back (" 5-5x5 Thin" );
106114 names.push_back (" 5-5x5 Mono" );
107115 names.push_back (" 6-5x6 Thin" );
@@ -119,7 +127,7 @@ const std::vector<std::string>& FontManager::get_font_names() {
119127 names.push_back (" 10-12x12 Thin Vertical" );
120128 names.push_back (" 12-15x15 Bold" );
121129 names.push_back (" 12-15x15 Bold Vertical" );
122- }
130+ });
123131
124132 return names;
125133}
0 commit comments