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

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

libbinder: delete dead server objects

We can do more active cleanup, and we can do kinder cleanup, but for now
fix leaks (future considerations/TODOs left in code).

Bug: 185167543
Test: binderRpcTest
Change-Id: Ide06476aefd72cbc46ba5fba095244a5448e493b
parent bdb53ab3
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -216,4 +216,16 @@ bool RpcServer::setupSocketServer(const RpcSocketAddress& addr) {
    return true;
}

void RpcServer::onSessionTerminating(const sp<RpcSession>& session) {
    auto id = session->mId;
    LOG_ALWAYS_FATAL_IF(id == std::nullopt, "Server sessions must be initialized with ID");
    LOG_RPC_DETAIL("Dropping session %d", *id);

    std::lock_guard<std::mutex> _l(mLock);
    auto it = mSessions.find(*id);
    LOG_ALWAYS_FATAL_IF(it == mSessions.end(), "Bad state, unknown session id %d", *id);
    LOG_ALWAYS_FATAL_IF(it->second != session, "Bad state, session has id mismatch %d", *id);
    (void)mSessions.erase(it);
}

} // namespace android
+20 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <string_view>

#include <binder/Parcel.h>
#include <binder/RpcServer.h>
#include <binder/Stability.h>
#include <utils/String8.h>

@@ -168,6 +169,22 @@ void RpcSession::join(unique_fd client) {
                        "bad state: connection object guaranteed to be in list");
}

void RpcSession::terminateLocked() {
    // TODO(b/185167543):
    // - kindly notify other side of the connection of termination (can't be
    // locked)
    // - prevent new client/servers from being added
    // - stop all threads which are currently reading/writing
    // - terminate RpcState?

    if (mTerminated) return;

    sp<RpcServer> server = mForServer.promote();
    if (server) {
        server->onSessionTerminating(sp<RpcSession>::fromExisting(this));
    }
}

wp<RpcServer> RpcSession::server() {
    return mForServer;
}
@@ -264,6 +281,9 @@ bool RpcSession::removeServerConnection(const sp<RpcConnection>& connection) {
    std::lock_guard<std::mutex> _l(mMutex);
    if (auto it = std::find(mServers.begin(), mServers.end(), connection); it != mServers.end()) {
        mServers.erase(it);
        if (mServers.size() == 0) {
            terminateLocked();
        }
        return true;
    }
    return false;
+4 −0
Original line number Diff line number Diff line
@@ -109,6 +109,10 @@ public:

    ~RpcServer();

    // internal use only

    void onSessionTerminating(const sp<RpcSession>& session);

private:
    friend sp<RpcServer>;
    RpcServer();
+2 −0
Original line number Diff line number Diff line
@@ -118,6 +118,7 @@ private:

    void startThread(base::unique_fd client);
    void join(base::unique_fd client);
    void terminateLocked();

    struct RpcConnection : public RefBase {
        base::unique_fd fd;
@@ -196,6 +197,7 @@ private:
    // TODO(b/185167543): allow sharing between different sessions in a
    // process? (or combine with mServers)
    std::map<std::thread::id, std::thread> mThreads;
    bool mTerminated = false;
};

} // namespace android