Merge "BufferQueue: Guard against unbounded queue growth"
This commit is contained in:
commit
4cbf3c5344
|
@ -160,8 +160,10 @@ status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
|
|||
}
|
||||
|
||||
mCore->mQueue.erase(front);
|
||||
// TODO: Should this call be after we free a slot while dropping buffers?
|
||||
// Simply acquiring the next buffer doesn't enable a producer to dequeue.
|
||||
|
||||
// We might have freed a slot while dropping old buffers, or the producer
|
||||
// may be blocked waiting for the number of buffers in the queue to
|
||||
// decrease.
|
||||
mCore->mDequeueCondition.broadcast();
|
||||
|
||||
ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
|
||||
|
|
|
@ -205,9 +205,21 @@ status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller,
|
|||
}
|
||||
}
|
||||
|
||||
// If no buffer is found, wait for a buffer to be released or for
|
||||
// the max buffer count to change
|
||||
tryAgain = (*found == BufferQueueCore::INVALID_BUFFER_SLOT);
|
||||
// If we disconnect and reconnect quickly, we can be in a state where
|
||||
// our slots are empty but we have many buffers in the queue. This can
|
||||
// cause us to run out of memory if we outrun the consumer. Wait here if
|
||||
// it looks like we have too many buffers queued up.
|
||||
bool tooManyBuffers = mCore->mQueue.size() > maxBufferCount;
|
||||
if (tooManyBuffers) {
|
||||
BQ_LOGV("%s: queue size is %d, waiting", caller,
|
||||
mCore->mQueue.size());
|
||||
}
|
||||
|
||||
// If no buffer is found, or if the queue has too many buffers
|
||||
// outstanding, wait for a buffer to be acquired or released, or for the
|
||||
// max buffer count to change.
|
||||
tryAgain = (*found == BufferQueueCore::INVALID_BUFFER_SLOT) ||
|
||||
tooManyBuffers;
|
||||
if (tryAgain) {
|
||||
// Return an error if we're in non-blocking mode (producer and
|
||||
// consumer are controlled by the application).
|
||||
|
@ -707,11 +719,6 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
|
|||
BQ_LOGV("connect(P): api=%d producerControlledByApp=%s", api,
|
||||
producerControlledByApp ? "true" : "false");
|
||||
|
||||
// If we disconnect and reconnect quickly, we can be in a state where our
|
||||
// slots are empty but we have many buffers in the queue. This can cause us
|
||||
// to run out of memory if we outrun the consumer. Wait here if it looks
|
||||
// like we have too many buffers queued up.
|
||||
while (true) {
|
||||
if (mCore->mIsAbandoned) {
|
||||
BQ_LOGE("connect(P): BufferQueue has been abandoned");
|
||||
return NO_INIT;
|
||||
|
@ -733,17 +740,6 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
|
|||
return BAD_VALUE;
|
||||
}
|
||||
|
||||
size_t maxBufferCount = mCore->getMaxBufferCountLocked(false);
|
||||
if (mCore->mQueue.size() <= maxBufferCount) {
|
||||
// The queue size seems small enough to proceed
|
||||
// TODO: Make this bound tighter?
|
||||
break;
|
||||
}
|
||||
|
||||
BQ_LOGV("connect(P): queue size is %d, waiting", mCore->mQueue.size());
|
||||
mCore->mDequeueCondition.wait(mCore->mMutex);
|
||||
}
|
||||
|
||||
int status = NO_ERROR;
|
||||
switch (api) {
|
||||
case NATIVE_WINDOW_API_EGL:
|
||||
|
|
Loading…
Reference in New Issue