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:
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 #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"
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue