diff options
author | Andreas Huber <andih@google.com> | 2010-04-12 13:10:20 -0700 |
---|---|---|
committer | Andreas Huber <andih@google.com> | 2010-04-12 13:15:48 -0700 |
commit | 874b55f51c4c062c65aee043ec0f26044b504556 (patch) | |
tree | 86d4c6cd8ec51091ae4998e326dd20392e983163 /media/libstagefright/TimedEventQueue.cpp | |
parent | b547d09ecc3da8ee300099da8ca7e2826bb6849a (diff) | |
download | frameworks_av-874b55f51c4c062c65aee043ec0f26044b504556.zip frameworks_av-874b55f51c4c062c65aee043ec0f26044b504556.tar.gz frameworks_av-874b55f51c4c062c65aee043ec0f26044b504556.tar.bz2 |
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.
Change-Id: I4e42e318fd5373d1f352f54027d4bf823126266d
related-to-bug: 2585276
Diffstat (limited to 'media/libstagefright/TimedEventQueue.cpp')
-rw-r--r-- | media/libstagefright/TimedEventQueue.cpp | 43 |
1 files changed, 34 insertions, 9 deletions
diff --git a/media/libstagefright/TimedEventQueue.cpp b/media/libstagefright/TimedEventQueue.cpp index e62d501..3de8c1d 100644 --- a/media/libstagefright/TimedEventQueue.cpp +++ b/media/libstagefright/TimedEventQueue.cpp @@ -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,18 +281,38 @@ 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); + } + + if (event != NULL) { + // Fire event with the lock NOT held. + event->fire(this, now_us); + } + } +} - event = (*it).event; +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 |