Skip to content

Commit adba698

Browse files
Danielle Jenkinsd6e
authored andcommitted
Fix race condition in FontFile data access during threaded imports
Add mutex protection to FontFile data access methods to prevent race conditions when multiple import threads access the same cached FontFile simultaneously. Use data_external flag to track whether data came from set_data_ptr() vs set_data() to avoid unnecessary PackedByteArray COW copies.
1 parent 7c26d93 commit adba698

File tree

2 files changed

+22
-5
lines changed

2 files changed

+22
-5
lines changed

scene/resources/font.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,8 @@ _FORCE_INLINE_ void FontFile::_ensure_rid(int p_cache_index, int p_make_linked_f
591591
if (p_make_linked_from >= 0 && p_make_linked_from != p_cache_index && p_make_linked_from < cache.size()) {
592592
cache.write[p_cache_index] = TS->create_font_linked_variation(cache[p_make_linked_from]);
593593
} else {
594+
MutexLock lock(data_mutex);
595+
594596
cache.write[p_cache_index] = TS->create_font();
595597
TS->font_set_data_ptr(cache[p_cache_index], data_ptr, data_size);
596598
TS->font_set_antialiasing(cache[p_cache_index], antialiasing);
@@ -1408,9 +1410,13 @@ void FontFile::_get_property_list(List<PropertyInfo> *p_list) const {
14081410

14091411
void FontFile::reset_state() {
14101412
_clear_cache();
1411-
data.clear();
1412-
data_ptr = nullptr;
1413-
data_size = 0;
1413+
{
1414+
MutexLock lock(data_mutex);
1415+
data = PackedByteArray();
1416+
data_ptr = nullptr;
1417+
data_size = 0;
1418+
data_external = false;
1419+
}
14141420
cache.clear();
14151421

14161422
antialiasing = TextServer::FONT_ANTIALIASING_GRAY;
@@ -2070,9 +2076,12 @@ Error FontFile::load_dynamic_font(const String &p_path) {
20702076
}
20712077

20722078
void FontFile::set_data_ptr(const uint8_t *p_data, size_t p_size) {
2073-
data.clear();
2079+
MutexLock lock(data_mutex);
2080+
2081+
data = PackedByteArray();
20742082
data_ptr = p_data;
20752083
data_size = p_size;
2084+
data_external = true;
20762085

20772086
for (int i = 0; i < cache.size(); i++) {
20782087
if (cache[i].is_valid()) {
@@ -2082,9 +2091,12 @@ void FontFile::set_data_ptr(const uint8_t *p_data, size_t p_size) {
20822091
}
20832092

20842093
void FontFile::set_data(const PackedByteArray &p_data) {
2094+
MutexLock lock(data_mutex);
2095+
20852096
data = p_data;
20862097
data_ptr = data.ptr();
20872098
data_size = data.size();
2099+
data_external = false;
20882100

20892101
for (int i = 0; i < cache.size(); i++) {
20902102
if (cache[i].is_valid()) {
@@ -2094,7 +2106,9 @@ void FontFile::set_data(const PackedByteArray &p_data) {
20942106
}
20952107

20962108
PackedByteArray FontFile::get_data() const {
2097-
if (unlikely((size_t)data.size() != data_size)) {
2109+
MutexLock lock(data_mutex);
2110+
2111+
if (unlikely(data_external && data.is_empty() && data_ptr && data_size > 0)) {
20982112
data.resize(data_size);
20992113
memcpy(data.ptrw(), data_ptr, data_size);
21002114
}

scene/resources/font.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#pragma once
3232

3333
#include "core/io/resource.h"
34+
#include "core/os/mutex.h"
3435
#include "core/templates/lru.h"
3536
#include "scene/resources/texture.h"
3637
#include "servers/text_server.h"
@@ -185,8 +186,10 @@ class FontFile : public Font {
185186
RES_BASE_EXTENSION("fontdata");
186187

187188
// Font source data.
189+
mutable Mutex data_mutex;
188190
const uint8_t *data_ptr = nullptr;
189191
size_t data_size = 0;
192+
bool data_external = false;
190193
mutable PackedByteArray data;
191194

192195
TextServer::FontAntialiasing antialiasing = TextServer::FONT_ANTIALIASING_GRAY;

0 commit comments

Comments
 (0)