libutils: RefBase: extra check for double own

Bug: 232557259
Test: libutils_test
Change-Id: Ibd400750e7973600ec3fa493838a3b52cafe3add
This commit is contained in:
Steven Moreland 2022-07-26 17:57:39 +00:00
parent ccb1ce32cc
commit 483a2def8d
2 changed files with 27 additions and 11 deletions

View File

@ -744,21 +744,27 @@ RefBase::~RefBase()
if (mRefs->mWeak.load(std::memory_order_relaxed) == 0) { if (mRefs->mWeak.load(std::memory_order_relaxed) == 0) {
delete mRefs; delete mRefs;
} }
} else if (mRefs->mStrong.load(std::memory_order_relaxed) == INITIAL_STRONG_VALUE) { } else {
// We never acquired a strong reference on this object. int32_t strongs = mRefs->mStrong.load(std::memory_order_relaxed);
// TODO: make this fatal, but too much code in Android manages RefBase with if (strongs == INITIAL_STRONG_VALUE) {
// new/delete manually (or using other mechanisms such as std::make_unique). // We never acquired a strong reference on this object.
// However, this is dangerous because it's also common for code to use the
// sp<T>(T*) constructor, assuming that if the object is around, it is already // It would be nice to make this fatal, but many places use RefBase on the stack.
// owned by an sp<>. // However, this is dangerous because it's also common for code to use the
ALOGW("RefBase: Explicit destruction, weak count = %d (in %p). Use sp<> to manage this " // sp<T>(T*) constructor, assuming that if the object is around, it is already
"object.", // owned by an sp<>.
mRefs->mWeak.load(), this); ALOGW("RefBase: Explicit destruction, weak count = %d (in %p). Use sp<> to manage this "
"object.",
mRefs->mWeak.load(), this);
#if CALLSTACK_ENABLED #if CALLSTACK_ENABLED
CallStack::logStack(LOG_TAG); CallStack::logStack(LOG_TAG);
#endif #endif
} else if (strongs != 0) {
LOG_ALWAYS_FATAL("RefBase: object %p with strong count %d deleted. Double owned?", this,
strongs);
}
} }
// For debugging purposes, clear mRefs. Ineffective against outstanding wp's. // For debugging purposes, clear mRefs. Ineffective against outstanding wp's.
const_cast<weakref_impl*&>(mRefs) = nullptr; const_cast<weakref_impl*&>(mRefs) = nullptr;

View File

@ -265,6 +265,16 @@ TEST(RefBase, AssertWeakRefExistsDeath) {
delete foo; delete foo;
} }
TEST(RefBase, DoubleOwnershipDeath) {
bool isDeleted;
auto foo = sp<Foo>::make(&isDeleted);
// if something else thinks it owns foo, should die
EXPECT_DEATH(delete foo.get(), "");
EXPECT_FALSE(isDeleted);
}
// Set up a situation in which we race with visit2AndRremove() to delete // Set up a situation in which we race with visit2AndRremove() to delete
// 2 strong references. Bar destructor checks that there are no early // 2 strong references. Bar destructor checks that there are no early
// deletions and prior updates are visible to destructor. // deletions and prior updates are visible to destructor.