Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cde5d53a authored by Steven Moreland's avatar Steven Moreland
Browse files

binderSafeInterfaceTest: avoid zombie

On 64-bit cuttlefish (and some other reported devices), this test was
failing to shut down properly (became a zombie process). In order to fix
this, this now forks a server much earlier, to avoid child processes
holding any resources.

Also, as an effect:
- no longer starting threadpool (only 1 thread is needed to process
test)
- using prctl to exit child process even in error cases

Bug: 174621701
Test: atest binderSafeInterfaceTest
 (on 64-bit cuttlefish, no longer hangs)
Change-Id: I326c42d0664e18c478efce83f935841e6dbfa8f3
parent 4aaa3105
Loading
Loading
Loading
Loading
+26 −32
Original line number Diff line number Diff line
@@ -36,12 +36,15 @@
#include <optional>

#include <sys/eventfd.h>
#include <sys/prctl.h>

using namespace std::chrono_literals; // NOLINT - google-build-using-namespace

namespace android {
namespace tests {

static const String16 kServiceName("SafeInterfaceTest");

enum class TestEnum : uint32_t {
    INVALID = 0,
    INITIAL = 1,
@@ -601,40 +604,13 @@ private:
    static constexpr const char* getLogTag() { return "SafeInterfaceTest"; }

    sp<ISafeInterfaceTest> getRemoteService() {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wexit-time-destructors"
        static std::mutex sMutex;
        static sp<ISafeInterfaceTest> sService;
        static sp<IBinder> sDeathToken = new BBinder;
#pragma clang diagnostic pop

        std::unique_lock<decltype(sMutex)> lock;
        if (sService == nullptr) {
            ALOG(LOG_INFO, getLogTag(), "Forking remote process");
            pid_t forkPid = fork();
            EXPECT_NE(forkPid, -1);

            const String16 serviceName("SafeInterfaceTest");

            if (forkPid == 0) {
                ALOG(LOG_INFO, getLogTag(), "Remote process checking in");
                sp<ISafeInterfaceTest> nativeService = new BnSafeInterfaceTest;
                defaultServiceManager()->addService(serviceName,
                                                    IInterface::asBinder(nativeService));
                ProcessState::self()->startThreadPool();
                IPCThreadState::self()->joinThreadPool();
                // We shouldn't get to this point
                [&]() { FAIL(); }();
            }

            sp<IBinder> binder = defaultServiceManager()->getService(serviceName);
            sService = interface_cast<ISafeInterfaceTest>(binder);
            EXPECT_TRUE(sService != nullptr);
        sp<IBinder> binder = defaultServiceManager()->getService(kServiceName);
        sp<ISafeInterfaceTest> iface = interface_cast<ISafeInterfaceTest>(binder);
        EXPECT_TRUE(iface != nullptr);

            sService->setDeathToken(sDeathToken);
        }
        iface->setDeathToken(new BBinder);

        return sService;
        return iface;
    }
};

@@ -840,5 +816,23 @@ TEST_F(SafeInterfaceTest, TestIncrementTwo) {
    ASSERT_EQ(b + 1, bPlusOne);
}

extern "C" int main(int argc, char **argv) {
    testing::InitGoogleTest(&argc, argv);

    if (fork() == 0) {
        prctl(PR_SET_PDEATHSIG, SIGHUP);
        sp<BnSafeInterfaceTest> nativeService = new BnSafeInterfaceTest;
        status_t status = defaultServiceManager()->addService(kServiceName, nativeService);
        if (status != OK) {
            ALOG(LOG_INFO, "SafeInterfaceServer", "could not register");
            return EXIT_FAILURE;
        }
        IPCThreadState::self()->joinThreadPool();
        return EXIT_FAILURE;
    }

    return RUN_ALL_TESTS();
}

} // namespace tests
} // namespace android