OSDN Git Service

Fix missing check on buffer import.
authorCorey Tabaka <eieio@google.com>
Sat, 29 Jul 2017 02:46:30 +0000 (19:46 -0700)
committerCorey Tabaka <eieio@google.com>
Sat, 29 Jul 2017 02:46:30 +0000 (19:46 -0700)
Fix a missing check on the success of importing buffers into the
ConsumerQueue. There is a race condition where the producer can
invalidate its buffers, for example by resizing, before the consumer
has a chance to import the previous buffers. The missing check
causes a crash in SurfaceFlinger and VrCore, which are both
consumers of application VR surface buffers.

Also fix a missing lock around the consumer queues in VR surfaces
found during the analysis of this bug.

Bug: 64042620
Test: Ran test.apk before and after the fix. Observe stable operation
      after applying the fix.

Change-Id: I416df3ca47978404dcdb53599ddeec9b4bd6fb1a

libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
libs/vr/libvrflinger/display_surface.cpp
libs/vr/libvrflinger/display_surface.h

index 3860390..bfb9a55 100644 (file)
@@ -613,6 +613,12 @@ Status<size_t> ConsumerQueue::ImportBuffers() {
 
     std::unique_ptr<BufferConsumer> buffer_consumer =
         BufferConsumer::Import(std::move(buffer_handle_slot.first));
+    if (!buffer_consumer) {
+      ALOGE("ConsumerQueue::ImportBuffers: Failed to import buffer: slot=%zu",
+            buffer_handle_slot.second);
+      last_error = ErrorStatus(EPIPE);
+      continue;
+    }
 
     // Setup ignore state before adding buffer to the queue.
     if (ignore_on_import_) {
index 04e3d5f..0d6a732 100644 (file)
@@ -194,6 +194,7 @@ std::shared_ptr<ConsumerQueue> ApplicationDisplaySurface::GetQueue(
            "ApplicationDisplaySurface::GetQueue: surface_id=%d queue_id=%d",
            surface_id(), queue_id);
 
+  std::lock_guard<std::mutex> autolock(lock_);
   auto search = consumer_queues_.find(queue_id);
   if (search != consumer_queues_.end())
     return search->second;
@@ -202,6 +203,7 @@ std::shared_ptr<ConsumerQueue> ApplicationDisplaySurface::GetQueue(
 }
 
 std::vector<int32_t> ApplicationDisplaySurface::GetQueueIds() const {
+  std::lock_guard<std::mutex> autolock(lock_);
   std::vector<int32_t> queue_ids;
   for (const auto& entry : consumer_queues_)
     queue_ids.push_back(entry.first);
@@ -270,6 +272,7 @@ void ApplicationDisplaySurface::OnQueueEvent(
 }
 
 std::vector<int32_t> DirectDisplaySurface::GetQueueIds() const {
+  std::lock_guard<std::mutex> autolock(lock_);
   std::vector<int32_t> queue_ids;
   if (direct_queue_)
     queue_ids.push_back(direct_queue_->id());
index 556183a..5cbee57 100644 (file)
@@ -133,6 +133,7 @@ class ApplicationDisplaySurface : public DisplaySurface {
   void OnQueueEvent(const std::shared_ptr<ConsumerQueue>& consumer_queue,
                     int events) override;
 
+  // Accessed by both message dispatch thread and epoll event thread.
   std::unordered_map<int32_t, std::shared_ptr<ConsumerQueue>> consumer_queues_;
 };