1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-16 15:29:55 +00:00

Initialize reserved names once to avoid race condition

CanOptimizeCallback::isReservedName function may be executed by multiple threads
simultaneously. One of them creates a static but both of them run if statement
and see it's empty because none of them added elements there yet. Both of them
go to the branch where new elements are added doing it without any
synchronization possibly causing SIGSEGV.
This commit is contained in:
elsid 2022-09-15 23:22:55 +02:00
parent ff90c9ce4f
commit 8068d0153f
No known key found for this signature in database
GPG key ID: 4DE04C198CBA7625
2 changed files with 64 additions and 16 deletions

View file

@ -179,6 +179,7 @@
Bug #6913: Constant effect enchanted items don't break invisibility Bug #6913: Constant effect enchanted items don't break invisibility
Bug #6923: Dispose of corpse prevents respawning after load Bug #6923: Dispose of corpse prevents respawning after load
Bug #6937: Divided by Nix Hounds quest is broken Bug #6937: Divided by Nix Hounds quest is broken
Bug #7008: Race condition on initializing a vector of reserved node names
Feature #890: OpenMW-CS: Column filtering Feature #890: OpenMW-CS: Column filtering
Feature #1465: "Reset" argument for AI functions Feature #1465: "Reset" argument for AI functions
Feature #2491: Ability to make OpenMW "portable" Feature #2491: Ability to make OpenMW "portable"

View file

@ -619,6 +619,67 @@ namespace Resource
return node; return node;
} }
std::vector<std::string> makeSortedReservedNames()
{
static constexpr std::string_view names[] = {
"Head",
"Neck",
"Chest",
"Groin",
"Right Hand",
"Left Hand",
"Right Wrist",
"Left Wrist",
"Shield Bone",
"Right Forearm",
"Left Forearm",
"Right Upper Arm",
"Left Upper Arm",
"Right Foot",
"Left Foot",
"Right Ankle",
"Left Ankle",
"Right Knee",
"Left Knee",
"Right Upper Leg",
"Left Upper Leg",
"Right Clavicle",
"Left Clavicle",
"Weapon Bone",
"Tail",
"Bip01",
"Root Bone",
"BoneOffset",
"AttachLight",
"Arrow",
"Camera",
"Collision",
"Right_Wrist",
"Left_Wrist",
"Shield_Bone",
"Right_Forearm",
"Left_Forearm",
"Right_Upper_Arm",
"Left_Clavicle",
"Weapon_Bone",
"Root_Bone",
};
std::vector<std::string> result;
result.reserve(std::size(names));
for (std::string_view name : names)
{
std::string prefixedName("Tri ");
prefixedName += name;
result.push_back(std::move(prefixedName));
}
std::sort(result.begin(), result.end(), Misc::StringUtils::ciLess);
return result;
}
} }
osg::ref_ptr<osg::Node> load (const std::string& normalizedFilename, const VFS::Manager* vfs, Resource::ImageManager* imageManager, Resource::NifFileManager* nifFileManager) osg::ref_ptr<osg::Node> load (const std::string& normalizedFilename, const VFS::Manager* vfs, Resource::ImageManager* imageManager, Resource::NifFileManager* nifFileManager)
@ -638,23 +699,9 @@ namespace Resource
if (name.empty()) if (name.empty())
return false; return false;
static std::vector<std::string> reservedNames; static const std::vector<std::string> reservedNames = makeSortedReservedNames();
if (reservedNames.empty())
{
const char* reserved[] = {"Head", "Neck", "Chest", "Groin", "Right Hand", "Left Hand", "Right Wrist", "Left Wrist", "Shield Bone", "Right Forearm", "Left Forearm", "Right Upper Arm",
"Left Upper Arm", "Right Foot", "Left Foot", "Right Ankle", "Left Ankle", "Right Knee", "Left Knee", "Right Upper Leg", "Left Upper Leg", "Right Clavicle",
"Left Clavicle", "Weapon Bone", "Tail", "Bip01", "Root Bone", "BoneOffset", "AttachLight", "Arrow", "Camera", "Collision", "Right_Wrist", "Left_Wrist",
"Shield_Bone", "Right_Forearm", "Left_Forearm", "Right_Upper_Arm", "Left_Clavicle", "Weapon_Bone", "Root_Bone"};
reservedNames = std::vector<std::string>(reserved, reserved + sizeof(reserved)/sizeof(reserved[0])); const auto it = Misc::partialBinarySearch(reservedNames.begin(), reservedNames.end(), name);
for (unsigned int i=0; i<sizeof(reserved)/sizeof(reserved[0]); ++i)
reservedNames.push_back(std::string("Tri ") + reserved[i]);
std::sort(reservedNames.begin(), reservedNames.end(), Misc::StringUtils::ciLess);
}
std::vector<std::string>::iterator it = Misc::partialBinarySearch(reservedNames.begin(), reservedNames.end(), name);
return it != reservedNames.end(); return it != reservedNames.end();
} }