mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
Merge pull request #11197 from hyperlogic/bug-fix/prevent-rig-crash-in-lambda
Rig: Use a registry to prevent use after free crashes/corruption
This commit is contained in:
commit
afce8b547a
2 changed files with 41 additions and 4 deletions
|
@ -32,6 +32,10 @@
|
|||
#include "AnimUtil.h"
|
||||
#include "IKTarget.h"
|
||||
|
||||
static int nextRigId = 1;
|
||||
static std::map<int, Rig*> rigRegistry;
|
||||
static std::mutex rigRegistryMutex;
|
||||
|
||||
static bool isEqual(const glm::vec3& u, const glm::vec3& v) {
|
||||
const float EPSILON = 0.0001f;
|
||||
return glm::length(u - v) / glm::length(u) <= EPSILON;
|
||||
|
@ -49,6 +53,26 @@ const glm::vec3 DEFAULT_RIGHT_EYE_POS(-0.3f, 0.9f, 0.0f);
|
|||
const glm::vec3 DEFAULT_LEFT_EYE_POS(0.3f, 0.9f, 0.0f);
|
||||
const glm::vec3 DEFAULT_HEAD_POS(0.0f, 0.75f, 0.0f);
|
||||
|
||||
Rig::Rig() {
|
||||
// Ensure thread-safe access to the rigRegistry.
|
||||
std::lock_guard<std::mutex> guard(rigRegistryMutex);
|
||||
|
||||
// Insert this newly allocated rig into the rig registry
|
||||
_rigId = nextRigId;
|
||||
rigRegistry[_rigId] = this;
|
||||
nextRigId++;
|
||||
}
|
||||
|
||||
Rig::~Rig() {
|
||||
// Ensure thread-safe access to the rigRegstry, but also prevent the rig from being deleted
|
||||
// while Rig::animationStateHandlerResult is being invoked on a script thread.
|
||||
std::lock_guard<std::mutex> guard(rigRegistryMutex);
|
||||
auto iter = rigRegistry.find(_rigId);
|
||||
if (iter != rigRegistry.end()) {
|
||||
rigRegistry.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
void Rig::overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame) {
|
||||
|
||||
UserAnimState::ClipNodeEnum clipNodeEnum;
|
||||
|
@ -935,8 +959,19 @@ void Rig::updateAnimationStateHandlers() { // called on avatar update thread (wh
|
|||
int identifier = data.key();
|
||||
StateHandler& value = data.value();
|
||||
QScriptValue& function = value.function;
|
||||
auto handleResult = [this, identifier](QScriptValue result) { // called in script thread to get the result back to us.
|
||||
animationStateHandlerResult(identifier, result);
|
||||
int rigId = _rigId;
|
||||
auto handleResult = [rigId, identifier](QScriptValue result) { // called in script thread to get the result back to us.
|
||||
// Hold the rigRegistryMutex to ensure thread-safe access to the rigRegistry, but
|
||||
// also to prevent the rig from being deleted while this lambda is being executed.
|
||||
std::lock_guard<std::mutex> guard(rigRegistryMutex);
|
||||
|
||||
// if the rig pointer is in the registry, it has not been deleted yet.
|
||||
auto iter = rigRegistry.find(rigId);
|
||||
if (iter != rigRegistry.end()) {
|
||||
Rig* rig = iter->second;
|
||||
assert(rig);
|
||||
rig->animationStateHandlerResult(identifier, result);
|
||||
}
|
||||
};
|
||||
// invokeMethod makes a copy of the args, and copies of AnimVariantMap do copy the underlying map, so this will correctly capture
|
||||
// the state of _animVars and allow continued changes to _animVars in this thread without conflict.
|
||||
|
|
|
@ -97,8 +97,8 @@ public:
|
|||
Hover
|
||||
};
|
||||
|
||||
Rig() {}
|
||||
virtual ~Rig() {}
|
||||
Rig();
|
||||
virtual ~Rig();
|
||||
|
||||
void destroyAnimGraph();
|
||||
|
||||
|
@ -372,6 +372,8 @@ protected:
|
|||
|
||||
glm::vec3 _prevLeftHandPoleVector { -Vectors::UNIT_Z };
|
||||
bool _prevLeftHandPoleVectorValid { false };
|
||||
|
||||
int _rigId;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__Rig__) */
|
||||
|
|
Loading…
Reference in a new issue