diff options
author | 2023-03-15 01:13:49 +0000 | |
---|---|---|
committer | 2023-03-15 01:22:50 +0000 | |
commit | 67f8590b3545f55a308a0ea7ec32a5bdedf9f619 (patch) | |
tree | 41d6c91aef9358bddc0c4d6a7875518ce1202875 /libs/binder/RpcState.cpp | |
parent | 69e22e9ea51f01b63e06a621a8c5a977617214fa (diff) |
Reland "RPC Binder: dropping all binders drops session"
This reverts commit 30a96fcc9ef87244469c93c0dea087008dad58fd.
Bug: 271830568
Fixes: 273486801 - also disabled clang-tidy check this is hitting
Test: binderRpcTest
Change-Id: I655cf2c2542b71aaab610cd9cbc5a7d53755178f
Diffstat (limited to 'libs/binder/RpcState.cpp')
-rw-r--r-- | libs/binder/RpcState.cpp | 38 |
1 files changed, 31 insertions, 7 deletions
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp index 38bd081b8b..ed3ce24e46 100644 --- a/libs/binder/RpcState.cpp +++ b/libs/binder/RpcState.cpp @@ -262,8 +262,10 @@ void RpcState::dump() { } void RpcState::clear() { - RpcMutexUniqueLock _l(mNodeMutex); + return clear(RpcMutexUniqueLock(mNodeMutex)); +} +void RpcState::clear(RpcMutexUniqueLock nodeLock) { if (mTerminated) { LOG_ALWAYS_FATAL_IF(!mNodeForAddress.empty(), "New state should be impossible after terminating!"); @@ -292,7 +294,7 @@ void RpcState::clear() { auto temp = std::move(mNodeForAddress); mNodeForAddress.clear(); // RpcState isn't reusable, but for future/explicit - _l.unlock(); + nodeLock.unlock(); temp.clear(); // explicit } @@ -704,7 +706,7 @@ status_t RpcState::sendDecStrongToTarget(const sp<RpcSession::RpcConnection>& co }; { - RpcMutexLockGuard _l(mNodeMutex); + RpcMutexUniqueLock _l(mNodeMutex); if (mTerminated) return DEAD_OBJECT; // avoid fatal only, otherwise races auto it = mNodeForAddress.find(addr); LOG_ALWAYS_FATAL_IF(it == mNodeForAddress.end(), @@ -720,8 +722,9 @@ status_t RpcState::sendDecStrongToTarget(const sp<RpcSession::RpcConnection>& co body.amount = it->second.timesRecd - target; it->second.timesRecd = target; - LOG_ALWAYS_FATAL_IF(nullptr != tryEraseNode(it), + LOG_ALWAYS_FATAL_IF(nullptr != tryEraseNode(session, std::move(_l), it), "Bad state. RpcState shouldn't own received binder"); + // LOCK ALREADY RELEASED } RpcWireHeader cmd = { @@ -1164,8 +1167,8 @@ status_t RpcState::processDecStrong(const sp<RpcSession::RpcConnection>& connect it->second.timesSent); it->second.timesSent -= body.amount; - sp<IBinder> tempHold = tryEraseNode(it); - _l.unlock(); + sp<IBinder> tempHold = tryEraseNode(session, std::move(_l), it); + // LOCK ALREADY RELEASED tempHold = nullptr; // destructor may make binder calls on this session return OK; @@ -1229,7 +1232,10 @@ status_t RpcState::validateParcel(const sp<RpcSession>& session, const Parcel& p return OK; } -sp<IBinder> RpcState::tryEraseNode(std::map<uint64_t, BinderNode>::iterator& it) { +sp<IBinder> RpcState::tryEraseNode(const sp<RpcSession>& session, RpcMutexUniqueLock nodeLock, + std::map<uint64_t, BinderNode>::iterator& it) { + bool shouldShutdown = false; + sp<IBinder> ref; if (it->second.timesSent == 0) { @@ -1239,9 +1245,27 @@ sp<IBinder> RpcState::tryEraseNode(std::map<uint64_t, BinderNode>::iterator& it) LOG_ALWAYS_FATAL_IF(!it->second.asyncTodo.empty(), "Can't delete binder w/ pending async transactions"); mNodeForAddress.erase(it); + + if (mNodeForAddress.size() == 0) { + shouldShutdown = true; + } } } + // If we shutdown, prevent RpcState from being re-used. This prevents another + // thread from getting the root object again. + if (shouldShutdown) { + clear(std::move(nodeLock)); + } else { + nodeLock.unlock(); // explicit + } + // LOCK IS RELEASED + + if (shouldShutdown) { + ALOGI("RpcState has no binders left, so triggering shutdown..."); + (void)session->shutdownAndWait(false); + } + return ref; } |