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

Commit aa20c581 authored by Alec Mouri's avatar Alec Mouri
Browse files

Clear out callback when canceling an alarm

VSyncDispatchTimerQueue tries to cancel its timer callback when
destroying itself, but Timekeeper might still run the callback if
disarming its timer happened immediately after polling but before
invoking the callback. To avoid this race condition, delete the callback
while holding Timekeeper's mutex.

Bug: 304675978
Test: builds
Change-Id: Ifa7a4fcb65481b6a5ddfcfeb6bc7a53cb37ec168
parent a3ba8119
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ private:
    void reset() EXCLUDES(mMutex);
    void cleanup() REQUIRES(mMutex);
    void setDebugState(DebugState) EXCLUDES(mMutex);
    void setCallback(std::function<void()>&&) REQUIRES(mMutex);

    int mTimerFd = -1;

@@ -71,6 +72,7 @@ private:
    void endDispatch();

    mutable std::mutex mMutex;

    std::function<void()> mCallback GUARDED_BY(mMutex);
    bool mExpectingCallback GUARDED_BY(mMutex) = false;
    DebugState mDebugState GUARDED_BY(mMutex);
+10 −4
Original line number Diff line number Diff line
@@ -93,8 +93,8 @@ void Timer::cleanup() {
        close(mPipes[kWritePipe]);
        mPipes[kWritePipe] = -1;
    }
    mExpectingCallback = false;
    mCallback = {};

    setCallback({});
}

void Timer::endDispatch() {
@@ -112,8 +112,7 @@ void Timer::alarmAt(std::function<void()> callback, nsecs_t time) {
    static constexpr int ns_per_s =
            std::chrono::duration_cast<std::chrono::nanoseconds>(1s).count();

    mCallback = std::move(callback);
    mExpectingCallback = true;
    setCallback(std::move(callback));

    struct itimerspec old_timer;
    struct itimerspec new_timer {
@@ -142,6 +141,8 @@ void Timer::alarmCancel() {
    if (timerfd_settime(mTimerFd, 0, &new_timer, &old_timer)) {
        ALOGW("Failed to disarm timerfd");
    }

    setCallback({});
}

void Timer::threadMain() {
@@ -231,6 +232,11 @@ void Timer::setDebugState(DebugState state) {
    mDebugState = state;
}

void Timer::setCallback(std::function<void()>&& callback) {
    mExpectingCallback = bool(callback);
    mCallback = std::move(callback);
}

void Timer::dump(std::string& result) const {
    std::lock_guard lock(mMutex);
    result.append("\t\tDebugState: ");