Add RpcServer::start()
start() starts a thread that runs join() in the background.
Because the thread can now be owned by RpcServer, shutdown() ensures
the thread is properly cleaned up.
Test: binderRpcTest
Bug: 182914638
Change-Id: I570d3d852e9eb4f6064dce934a2fdb3bc8f210f7
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index 73facc1..50b0465 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -128,6 +128,17 @@
return ret;
}
+static void joinRpcServer(sp<RpcServer>&& thiz) {
+ thiz->join();
+}
+
+void RpcServer::start() {
+ LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
+ std::lock_guard<std::mutex> _l(mLock);
+ LOG_ALWAYS_FATAL_IF(mJoinThread.get(), "Already started!");
+ mJoinThread = std::make_unique<std::thread>(&joinRpcServer, sp<RpcServer>::fromExisting(this));
+}
+
void RpcServer::join() {
LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
@@ -178,6 +189,17 @@
mShutdownTrigger->trigger();
while (mJoinThreadRunning) mShutdownCv.wait(_l);
+ // At this point, we know join() is about to exit, but the thread that calls
+ // join() may not have exited yet.
+ // If RpcServer owns the join thread (aka start() is called), make sure the thread exits;
+ // otherwise ~thread() may call std::terminate(), which may crash the process.
+ // If RpcServer does not own the join thread (aka join() is called directly),
+ // then the owner of RpcServer is responsible for cleaning up that thread.
+ if (mJoinThread.get()) {
+ mJoinThread->join();
+ mJoinThread.reset();
+ }
+
mShutdownTrigger = nullptr;
return true;
}
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
index f76ecc2..50770f1 100644
--- a/libs/binder/include/binder/RpcServer.h
+++ b/libs/binder/include/binder/RpcServer.h
@@ -117,6 +117,11 @@
sp<IBinder> getRootObject();
/**
+ * Runs join() in a background thread. Immediately returns.
+ */
+ void start();
+
+ /**
* You must have at least one client session before calling this.
*
* If a client needs to actively terminate join, call shutdown() in a separate thread.
@@ -159,12 +164,13 @@
base::unique_fd mServer; // socket we are accepting sessions on
std::mutex mLock; // for below
+ std::unique_ptr<std::thread> mJoinThread;
+ bool mJoinThreadRunning = false;
std::map<std::thread::id, std::thread> mConnectingThreads;
sp<IBinder> mRootObject;
wp<IBinder> mRootObjectWeak;
std::map<int32_t, sp<RpcSession>> mSessions;
int32_t mSessionIdCounter = 0;
- bool mJoinThreadRunning = false;
std::unique_ptr<RpcSession::FdTrigger> mShutdownTrigger;
std::condition_variable mShutdownCv;
};