libutils: RefBase: extra check for double own
Bug: 232557259 Test: libutils_test Change-Id: Ibd400750e7973600ec3fa493838a3b52cafe3add
This commit is contained in:
parent
ccb1ce32cc
commit
483a2def8d
|
@ -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;
|
||||||
|
|
|
@ -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.
|
||||||
|
|
Loading…
Reference in New Issue