Merge "libbinder: ProcessState warn on forked"
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 94b2806..e2ab515 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -89,13 +89,23 @@
     return init(nullptr, false /*requireDefault*/);
 }
 
+[[clang::no_destroy]] static sp<ProcessState> gProcess;
+[[clang::no_destroy]] static std::mutex gProcessMutex;
+
+static void verifyNotForked(bool forked) {
+    if (forked) {
+        ALOGE("libbinder does not support being forked");
+    }
+}
+
 sp<ProcessState> ProcessState::init(const char *driver, bool requireDefault)
 {
-    [[clang::no_destroy]] static sp<ProcessState> gProcess;
-    [[clang::no_destroy]] static std::mutex gProcessMutex;
 
     if (driver == nullptr) {
         std::lock_guard<std::mutex> l(gProcessMutex);
+        if (gProcess) {
+            verifyNotForked(gProcess->mForked);
+        }
         return gProcess;
     }
 
@@ -106,6 +116,14 @@
             driver = "/dev/binder";
         }
 
+        // we must install these before instantiating the gProcess object,
+        // otherwise this would race with creating it, and there could be the
+        // possibility of an invalid gProcess object forked by another thread
+        // before these are installed
+        int ret = pthread_atfork(ProcessState::onFork, ProcessState::parentPostFork,
+                                 ProcessState::childPostFork);
+        LOG_ALWAYS_FATAL_IF(ret != 0, "pthread_atfork error %s", strerror(ret));
+
         std::lock_guard<std::mutex> l(gProcessMutex);
         gProcess = sp<ProcessState>::make(driver);
     });
@@ -119,6 +137,7 @@
                             gProcess->getDriverName().c_str(), driver);
     }
 
+    verifyNotForked(gProcess->mForked);
     return gProcess;
 }
 
@@ -137,6 +156,24 @@
     return context;
 }
 
+void ProcessState::onFork() {
+    // make sure another thread isn't currently retrieving ProcessState
+    gProcessMutex.lock();
+}
+
+void ProcessState::parentPostFork() {
+    gProcessMutex.unlock();
+}
+
+void ProcessState::childPostFork() {
+    // another thread might call fork before gProcess is instantiated, but after
+    // the thread handler is installed
+    if (gProcess) {
+        gProcess->mForked = true;
+    }
+    gProcessMutex.unlock();
+}
+
 void ProcessState::startThreadPool()
 {
     AutoMutex _l(mLock);
@@ -426,6 +463,7 @@
         mWaitingForThreads(0),
         mMaxThreads(DEFAULT_MAX_BINDER_THREADS),
         mStarvationStartTimeMs(0),
+        mForked(false),
         mThreadPoolStarted(false),
         mThreadPoolSeq(1),
         mCallRestriction(CallRestriction::NONE) {
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index 72c2ab7..cf8d8e4 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -94,6 +94,10 @@
 private:
     static sp<ProcessState> init(const char* defaultDriver, bool requireDefault);
 
+    static void onFork();
+    static void parentPostFork();
+    static void childPostFork();
+
     friend class IPCThreadState;
     friend class sp<ProcessState>;
 
@@ -132,6 +136,7 @@
 
     Vector<handle_entry> mHandleToObject;
 
+    bool mForked;
     bool mThreadPoolStarted;
     volatile int32_t mThreadPoolSeq;