mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-20 14:23:53 +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:
parent
ff90c9ce4f
commit
8068d0153f
2 changed files with 64 additions and 16 deletions
|
@ -179,6 +179,7 @@
|
|||
Bug #6913: Constant effect enchanted items don't break invisibility
|
||||
Bug #6923: Dispose of corpse prevents respawning after load
|
||||
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 #1465: "Reset" argument for AI functions
|
||||
Feature #2491: Ability to make OpenMW "portable"
|
||||
|
|
|
@ -619,6 +619,67 @@ namespace Resource
|
|||
|
||||
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)
|
||||
|
@ -638,23 +699,9 @@ namespace Resource
|
|||
if (name.empty())
|
||||
return false;
|
||||
|
||||
static std::vector<std::string> reservedNames;
|
||||
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"};
|
||||
static const std::vector<std::string> reservedNames = makeSortedReservedNames();
|
||||
|
||||
reservedNames = std::vector<std::string>(reserved, reserved + sizeof(reserved)/sizeof(reserved[0]));
|
||||
|
||||
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);
|
||||
const auto it = Misc::partialBinarySearch(reservedNames.begin(), reservedNames.end(), name);
|
||||
return it != reservedNames.end();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue