Skip to content

Commit 08925ac

Browse files
authored
Fix Text effect font-cache race to allow deterministic renders (#6959)
1 parent 9db0bb1 commit 08925ac

3 files changed

Lines changed: 16 additions & 4 deletions

File tree

README.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ XLIGHTS/NUTCRACKER RELEASE NOTES
1212
---------------------------------
1313
2026.16 August ??, 2026
1414

15+
-bug (derwin12) Fix Text effect rendering nondeterministically (and occasionally crashing)
1516
-bug (dkulp) FPP Connect: uploading UDP outputs no longer resets FPP10's E1.31 Pacing
1617
and Sending mode - every setting on the universes output that xLights
1718
does not own is now carried forward unchanged

src-core/render/FontManager.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,20 @@ FontManager::FontManager() {
6363
std::vector<std::unique_ptr<xlFont>> FontManager::fonts;
6464
bool FontManager::initialized = false;
6565
std::vector<std::string> FontManager::names;
66+
std::once_flag FontManager::initOnceFlag;
67+
std::once_flag FontManager::namesOnceFlag;
6668

6769
FontManager::~FontManager() {
6870
}
6971

7072
void 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

103111
const 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
}

src-core/render/FontManager.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
**************************************************************/
1212

1313
#include <memory>
14+
#include <mutex>
1415
#include <string>
1516
#include <vector>
1617

@@ -67,4 +68,6 @@ class FontManager {
6768
static std::vector<std::unique_ptr<xlFont>> fonts;
6869
static bool initialized;
6970
static std::vector<std::string> names;
71+
static std::once_flag initOnceFlag;
72+
static std::once_flag namesOnceFlag;
7073
};

0 commit comments

Comments
 (0)