Fixes a lock reentrancy when destroying a mock causes destruction of another mock (issue 79) (by Aaron Jacobs).

This commit is contained in:
vladlosev
2011-10-24 23:41:07 +00:00
parent 4d60a596b4
commit 9bcb5f9146
3 changed files with 85 additions and 5 deletions

View File

@@ -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: