Fix thread safety issues in UsdSkel_SkelDefinition. #2369
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description of Change(s)
In methods like
_ComputeJointWorldInverseBindTransforms()
, check the compute flag again after acquiring the lock to avoid potentially recomputing the result again if multiple threads were waiting on the mutex. Although the computed values would not change, it is not safe to call mutable member functions of the VtArray (which can cause a copy-on-write detach) while other threads may be in the middle of making a copy of it. An example sequence that could lead to a crash:_GetJointWorldInverseBindTransforms()
(refcount == 2)_DetachIfNotUnique()
since_IsUnique()
is false_GetJointWorldInverseBindTransforms()
and observes that the compute flag is set, and starts to make its own copy of the array, but hasn't bumped the refcount yet.Prefer using
operator|=
to atomically set the flag rather than doing a read -> bitwise OR -> atomic store sequence which could cause flags to be lost if there are concurrent writes. Currently the writes are all guarded by the same mutex so the previous approach was not actually problematic, but this is safer if e.g. in the future there are separate locks for each cached array.This isn't the easiest to reproduce (e.g. Storm will not encounter this, since it computes the skinning transforms during the single-threaded sprim sync), but I had a customer file that reproduced this very reliably in the Houdini GL delegate with a 32-core machine, and verified that this fix resolved the issue.
Fixes Issue(s)