aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorvladlosev <vladlosev@8415998a-534a-0410-bf83-d39667b30386>2011-10-24 23:41:07 +0000
committervladlosev <vladlosev@8415998a-534a-0410-bf83-d39667b30386>2011-10-24 23:41:07 +0000
commit9bcb5f9146db42bc38b6bb744fb0cf518a0205be (patch)
tree25eaddb193823d54b9dce3878b0f32d2eba6739a /include
parent4d60a596b4135c5a7e21ef7b4fe24a5c90329e0f (diff)
downloadgoogletest-9bcb5f9146db42bc38b6bb744fb0cf518a0205be.tar.gz
googletest-9bcb5f9146db42bc38b6bb744fb0cf518a0205be.tar.bz2
googletest-9bcb5f9146db42bc38b6bb744fb0cf518a0205be.zip
Fixes a lock reentrancy when destroying a mock causes destruction of another mock (issue 79) (by Aaron Jacobs).
Diffstat (limited to 'include')
-rw-r--r--include/gmock/gmock-spec-builders.h21
1 files changed, 18 insertions, 3 deletions
diff --git a/include/gmock/gmock-spec-builders.h b/include/gmock/gmock-spec-builders.h
index 1953e43a..36c47d67 100644
--- a/include/gmock/gmock-spec-builders.h
+++ b/include/gmock/gmock-spec-builders.h
@@ -1475,12 +1475,27 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
virtual void ClearDefaultActionsLocked()
GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
g_gmock_mutex.AssertHeld();
+
+ // Deleting our default actions may trigger other mock objects to be
+ // deleted, for example if an action contains a reference counted smart
+ // pointer to that mock object, and that is the last reference. So if we
+ // delete our actions within the context of the global mutex we may deadlock
+ // when this method is called again. Instead, make a copy of the set of
+ // actions to delete, clear our set within the mutex, and then delete the
+ // actions outside of the mutex.
+ UntypedOnCallSpecs specs_to_delete;
+ untyped_on_call_specs_.swap(specs_to_delete);
+
+ g_gmock_mutex.Unlock();
for (UntypedOnCallSpecs::const_iterator it =
- untyped_on_call_specs_.begin();
- it != untyped_on_call_specs_.end(); ++it) {
+ specs_to_delete.begin();
+ it != specs_to_delete.end(); ++it) {
delete static_cast<const OnCallSpec<F>*>(*it);
}
- untyped_on_call_specs_.clear();
+
+ // Lock the mutex again, since the caller expects it to be locked when we
+ // return.
+ g_gmock_mutex.Lock();
}
protected: