From 03f4e14ec612d53b5e2b987555b24afcbbe319d1 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Mon, 29 Mar 2010 11:52:08 -0700 Subject: Fix a bug where the TimedEventQueue mistakenly accesses a bogus event if the only event in the queue has been cancelled while we're waiting for its scheduled time. Avoids potential int64_t overflow when converting from us to ns. Change-Id: I50e8976ce8d0ecc47ee0eb497296930877ce306a related-to-bug: 2549465 --- media/libstagefright/TimedEventQueue.cpp | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) (limited to 'media/libstagefright/TimedEventQueue.cpp') diff --git a/media/libstagefright/TimedEventQueue.cpp b/media/libstagefright/TimedEventQueue.cpp index 6307bc5..e62d501 100644 --- a/media/libstagefright/TimedEventQueue.cpp +++ b/media/libstagefright/TimedEventQueue.cpp @@ -24,6 +24,7 @@ #include "include/TimedEventQueue.h" +#include #include #include @@ -182,7 +183,7 @@ int64_t TimedEventQueue::getRealTimeUs() { struct timeval tv; gettimeofday(&tv, NULL); - return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec; + return (int64_t)tv.tv_sec * 1000000ll + tv.tv_usec; } // static @@ -211,8 +212,10 @@ void *TimedEventQueue::ThreadWrapper(void *me) { } void TimedEventQueue::threadEntry() { + prctl(PR_SET_NAME, (unsigned long)"TimedEventQueue", 0, 0, 0); + for (;;) { - int64_t now_us; + int64_t now_us = 0; sp event; { @@ -228,6 +231,11 @@ void TimedEventQueue::threadEntry() { List::iterator it; 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(); now_us = getRealTimeUs(); @@ -244,10 +252,25 @@ void TimedEventQueue::threadEntry() { break; } + static int64_t kMaxTimeoutUs = 10000000ll; // 10 secs + bool timeoutCapped = false; + if (delay_us > kMaxTimeoutUs) { + LOGW("delay_us exceeds max timeout: %lld us", delay_us); + + // We'll never block for more than 10 secs, instead + // we will split up the full timeout into chunks of + // 10 secs at a time. This will also avoid overflow + // when converting from us to ns. + delay_us = kMaxTimeoutUs; + timeoutCapped = true; + } + status_t err = mQueueHeadChangedCondition.waitRelative( - mLock, delay_us * 1000); + mLock, delay_us * 1000ll); - if (err == -ETIMEDOUT) { + if (!timeoutCapped && err == -ETIMEDOUT) { + // We finally hit the time this event is supposed to + // trigger. now_us = getRealTimeUs(); break; } -- cgit v1.1