diff options
-rw-r--r-- | libs/binder/RpcServer.cpp | 15 | ||||
-rw-r--r-- | libs/binder/RpcSession.cpp | 4 | ||||
-rw-r--r-- | libs/binder/include/binder/RpcSession.h | 5 |
3 files changed, 20 insertions, 4 deletions
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp index 3a98cadb94..06c3a4206d 100644 --- a/libs/binder/RpcServer.cpp +++ b/libs/binder/RpcServer.cpp @@ -22,6 +22,7 @@ #include <thread> #include <vector> +#include <android-base/scopeguard.h> #include <binder/Parcel.h> #include <binder/RpcServer.h> #include <log/log.h> @@ -32,6 +33,7 @@ namespace android { +using base::ScopeGuard; using base::unique_fd; RpcServer::RpcServer() {} @@ -157,10 +159,11 @@ void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clie // TODO(b/183988761): cannot trust this simple ID LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!"); + bool idValid = true; int32_t id; if (sizeof(id) != read(clientFd.get(), &id, sizeof(id))) { ALOGE("Could not read ID from fd %d", clientFd.get()); - return; + idValid = false; } std::thread thisThread; @@ -172,8 +175,13 @@ void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clie LOG_ALWAYS_FATAL_IF(threadId == mConnectingThreads.end(), "Must establish connection on owned thread"); thisThread = std::move(threadId->second); + ScopeGuard detachGuard = [&]() { thisThread.detach(); }; mConnectingThreads.erase(threadId); + if (!idValid) { + return; + } + if (id == RPC_SESSION_ID_NEW) { LOG_ALWAYS_FATAL_IF(mSessionIdCounter >= INT32_MAX, "Out of session IDs"); mSessionIdCounter++; @@ -190,6 +198,9 @@ void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clie } session = it->second; } + + detachGuard.Disable(); + session->preJoin(std::move(thisThread)); } // avoid strong cycle @@ -199,7 +210,7 @@ void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clie // DO NOT ACCESS MEMBER VARIABLES BELOW // - session->join(std::move(thisThread), std::move(clientFd)); + session->join(std::move(clientFd)); } bool RpcServer::setupSocketServer(const RpcSocketAddress& addr) { diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp index f32aa7a72d..05fa49ec76 100644 --- a/libs/binder/RpcSession.cpp +++ b/libs/binder/RpcSession.cpp @@ -131,14 +131,16 @@ status_t RpcSession::readId() { return OK; } -void RpcSession::join(std::thread thread, unique_fd client) { +void RpcSession::preJoin(std::thread thread) { LOG_ALWAYS_FATAL_IF(thread.get_id() != std::this_thread::get_id(), "Must own this thread"); { std::lock_guard<std::mutex> _l(mMutex); mThreads[thread.get_id()] = std::move(thread); } +} +void RpcSession::join(unique_fd client) { // must be registered to allow arbitrary client code executing commands to // be able to do nested calls (we can't only read from it) sp<RpcConnection> connection = assignServerToThisThread(std::move(client)); diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h index 92ee100dc5..bcc213c8bd 100644 --- a/libs/binder/include/binder/RpcSession.h +++ b/libs/binder/include/binder/RpcSession.h @@ -114,7 +114,10 @@ private: status_t readId(); - void join(std::thread thread, base::unique_fd client); + // transfer ownership of thread + void preJoin(std::thread thread); + // join on thread passed to preJoin + void join(base::unique_fd client); void terminateLocked(); struct RpcConnection : public RefBase { |