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

Commit ff118cec authored by David Anderson's avatar David Anderson
Browse files

libsnapshot: Add a way to detach snapuserd.

Currently, when init unlinks /dev/socket/snapuserd, the daemon currently
polling the socket will fail in accept4(). This works because the
process won't exit until all threads have terminated, but it's
confusing, and it creates log spam.

Instead, add an explicit "detach" message so that snapuserd will stop
listening for new connections and will immediately join on remaining
threads. This way snapuserd will gracefully exit when all threads are
complete, and we're guaranteed no new threads will be created.

This will only be used for first-stage instances of snapuserd.

Bug: 173476209
Test: full OTA with VABC, no accept4() errors
Change-Id: Ibeffa4a35043ed43a70166eeee86204e2b3d03aa
parent 5aa05fce
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -70,6 +70,11 @@ class SnapuserdClient {
    // Wait for snapuserd to disassociate with a dm-user control device. This
    // must ONLY be called if the control device has already been deleted.
    bool WaitForDeviceDelete(const std::string& control_device);

    // Detach snapuserd. This shuts down the listener socket, and will cause
    // snapuserd to gracefully exit once all handler threads have terminated.
    // This should only be used on first-stage instances of snapuserd.
    bool DetachSnapuserd();
};

}  // namespace snapshot
+2 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ enum class DaemonOperations {
    QUERY,
    STOP,
    DELETE,
    DETACH,
    INVALID,
};

@@ -106,6 +107,7 @@ class SnapuserdServer : public Stoppable {
    bool IsTerminating() { return terminating_; }

    void RunThread(std::shared_ptr<DmUserHandler> handler);
    void JoinAllThreads();

    // Find a DmUserHandler within a lock.
    HandlerList::iterator FindHandler(std::lock_guard<std::mutex>* proof_of_lock,
+8 −0
Original line number Diff line number Diff line
@@ -210,5 +210,13 @@ uint64_t SnapuserdClient::InitDmUserCow(const std::string& misc_name, const std:
    return num_sectors;
}

bool SnapuserdClient::DetachSnapuserd() {
    if (!Sendmsg("detach")) {
        LOG(ERROR) << "Failed to detach snapuserd.";
        return false;
    }
    return true;
}

}  // namespace snapshot
}  // namespace android
+24 −14
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ DaemonOperations SnapuserdServer::Resolveop(std::string& input) {
    if (input == "stop") return DaemonOperations::STOP;
    if (input == "query") return DaemonOperations::QUERY;
    if (input == "delete") return DaemonOperations::DELETE;
    if (input == "detach") return DaemonOperations::DETACH;

    return DaemonOperations::INVALID;
}
@@ -72,19 +73,7 @@ void SnapuserdServer::Parsemsg(std::string const& msg, const char delim,

void SnapuserdServer::ShutdownThreads() {
    StopThreads();

    // Acquire the thread list within the lock.
    std::vector<std::shared_ptr<DmUserHandler>> dm_users;
    {
        std::lock_guard<std::mutex> guard(lock_);
        dm_users = std::move(dm_users_);
    }

    for (auto& client : dm_users) {
        auto& th = client->thread();

        if (th.joinable()) th.join();
    }
    JoinAllThreads();
}

const std::string& DmUserHandler::GetMiscName() const {
@@ -214,6 +203,10 @@ bool SnapuserdServer::Receivemsg(android::base::borrowed_fd fd, const std::strin
            }
            return Sendmsg(fd, "success");
        }
        case DaemonOperations::DETACH: {
            terminating_ = true;
            return Sendmsg(fd, "success");
        }
        default: {
            LOG(ERROR) << "Received unknown message type from client";
            Sendmsg(fd, "fail");
@@ -234,7 +227,7 @@ void SnapuserdServer::RunThread(std::shared_ptr<DmUserHandler> handler) {

    LOG(INFO) << "Exiting thread for handler: " << handler->GetMiscName();

    // If the main thread called /emoveHandler, the handler was already removed
    // If the main thread called RemoveHandler, the handler was already removed
    // from within the lock, and calling RemoveHandler again has no effect.
    RemoveHandler(handler->GetMiscName(), false);
}
@@ -286,9 +279,26 @@ bool SnapuserdServer::Run() {
            }
        }
    }

    JoinAllThreads();
    return true;
}

void SnapuserdServer::JoinAllThreads() {
    // Acquire the thread list within the lock.
    std::vector<std::shared_ptr<DmUserHandler>> dm_users;
    {
        std::lock_guard<std::mutex> guard(lock_);
        dm_users = std::move(dm_users_);
    }

    for (auto& client : dm_users) {
        auto& th = client->thread();

        if (th.joinable()) th.join();
    }
}

void SnapuserdServer::AddWatchedFd(android::base::borrowed_fd fd) {
    struct pollfd p = {};
    p.fd = fd.get();