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

Commit fac0c29e authored by Andreas Huber's avatar Andreas Huber Committed by Android Git Automerger
Browse files

am 98c5bd55: am 6dbf80d0: Merge "Fix a race condition in TimedEventQueue, an...

am 98c5bd55: am 6dbf80d0: Merge "Fix a race condition in TimedEventQueue, an event may be cancelled while we\'re waiting for its scheduled time to come in which case we\'d be removing it from the queue twice." into froyo

Merge commit '98c5bd55' into kraken

* commit '98c5bd55':
  Fix a race condition in TimedEventQueue, an event may be cancelled while we're waiting for its scheduled time to come in which case we'd be removing it from the queue twice.
parents a753fbe0 98c5bd55
Loading
Loading
Loading
Loading
+34 −9
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#define __STDC_LIMIT_MACROS
#include <stdint.h>

//#define LOG_NDEBUG 0
#define LOG_TAG "TimedEventQueue"
#include <utils/Log.h>

@@ -169,6 +170,8 @@ void TimedEventQueue::cancelEvents(
            mQueueHeadChangedCondition.signal();
        }

        LOGV("cancelling event %d", (*it).event->eventID());

        (*it).event->setEventID(0);
        it = mQueue.erase(it);

@@ -229,14 +232,16 @@ void TimedEventQueue::threadEntry() {
                mQueueNotEmptyCondition.wait(mLock);
            }

            List<QueueItem>::iterator it;
            event_id eventID = 0;
            for (;;) {
                if (mQueue.empty()) {
                    // The only event in the queue could have been cancelled
                    // while we were waiting for its scheduled time.
                    break;
                }
                it = mQueue.begin();

                List<QueueItem>::iterator it = mQueue.begin();
                eventID = (*it).event->eventID();

                now_us = getRealTimeUs();
                int64_t when_us = (*it).realtime_us;
@@ -276,19 +281,39 @@ void TimedEventQueue::threadEntry() {
                }
            }

            if (mQueue.empty()) {
                continue;
            // The event w/ this id may have been cancelled while we're
            // waiting for its trigger-time, in that case
            // removeEventFromQueue_l will return NULL.
            // Otherwise, the QueueItem will be removed
            // from the queue and the referenced event returned.
            event = removeEventFromQueue_l(eventID);
        }

            event = (*it).event;
        if (event != NULL) {
            // Fire event with the lock NOT held.
            event->fire(this, now_us);
        }
    }
}

sp<TimedEventQueue::Event> TimedEventQueue::removeEventFromQueue_l(
        event_id id) {
    for (List<QueueItem>::iterator it = mQueue.begin();
         it != mQueue.end(); ++it) {
        if ((*it).event->eventID() == id) {
            sp<Event> event = (*it).event;
            event->setEventID(0);

            mQueue.erase(it);
        }

        // Fire event with the lock NOT held.
        event->fire(this, now_us);
            return event;
        }
    }

    LOGW("Event %d was not found in the queue, already cancelled?", id);

    return NULL;
}

}  // namespace android
+2 −0
Original line number Diff line number Diff line
@@ -121,6 +121,8 @@ private:
    static void *ThreadWrapper(void *me);
    void threadEntry();

    sp<Event> removeEventFromQueue_l(event_id id);

    TimedEventQueue(const TimedEventQueue &);
    TimedEventQueue &operator=(const TimedEventQueue &);
};