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.
make_linux_ci_do_zoomies
elsid 2 years ago
parent ff90c9ce4f
commit 8068d0153f
No known key found for this signature in database
GPG Key ID: 4DE04C198CBA7625

@ -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"};
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);
}
static const std::vector<std::string> reservedNames = makeSortedReservedNames();
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…
Cancel
Save