summarylogtreecommitdiffstats
path: root/0005-ozone-wayland-Use-mutex-before-accessing-surfaces-ma.patch
diff options
context:
space:
mode:
Diffstat (limited to '0005-ozone-wayland-Use-mutex-before-accessing-surfaces-ma.patch')
-rw-r--r--0005-ozone-wayland-Use-mutex-before-accessing-surfaces-ma.patch276
1 files changed, 276 insertions, 0 deletions
diff --git a/0005-ozone-wayland-Use-mutex-before-accessing-surfaces-ma.patch b/0005-ozone-wayland-Use-mutex-before-accessing-surfaces-ma.patch
new file mode 100644
index 000000000000..9a4e8e822cb3
--- /dev/null
+++ b/0005-ozone-wayland-Use-mutex-before-accessing-surfaces-ma.patch
@@ -0,0 +1,276 @@
+From fd1d8bfd55d5b1d073cbad3ebe8f058c49f3702a Mon Sep 17 00:00:00 2001
+From: Maksim Sisov <msisov@igalia.com>
+Date: Mon, 5 Aug 2019 16:14:47 +0300
+Subject: [PATCH 5/5] [ozone/wayland] Use mutex before accessing surfaces map.
+
+We must make sure that accessing surfaces map from different threads
+is safe. Otherwise, this is subject to races and unexpected crashes.
+
+Bug: 987950
+Change-Id: I2e70e9c1ad48943be518c3571b7ca1fb91f8d51b
+---
+ ui/ozone/platform/wayland/BUILD.gn | 1 +
+ .../wayland/gpu/gbm_pixmap_wayland.cc | 6 +-
+ .../wayland/gpu/gbm_surfaceless_wayland.cc | 2 +-
+ .../wayland/gpu/wayland_buffer_manager_gpu.cc | 61 ++++++++-----------
+ .../wayland/gpu/wayland_buffer_manager_gpu.h | 14 ++++-
+ .../wayland/gpu/wayland_canvas_surface.cc | 2 +-
+ .../wayland/gpu/wayland_surface_gpu.cc | 16 +++++
+ .../wayland/gpu/wayland_surface_gpu.h | 13 +++-
+ 8 files changed, 72 insertions(+), 43 deletions(-)
+ create mode 100644 ui/ozone/platform/wayland/gpu/wayland_surface_gpu.cc
+
+diff --git a/ui/ozone/platform/wayland/BUILD.gn b/ui/ozone/platform/wayland/BUILD.gn
+index 686138bb614a..a1560a20fe23 100644
+--- a/ui/ozone/platform/wayland/BUILD.gn
++++ b/ui/ozone/platform/wayland/BUILD.gn
+@@ -30,6 +30,7 @@ source_set("wayland") {
+ "gpu/wayland_canvas_surface.h",
+ "gpu/wayland_surface_factory.cc",
+ "gpu/wayland_surface_factory.h",
++ "gpu/wayland_surface_gpu.cc",
+ "gpu/wayland_surface_gpu.h",
+ "host/wayland_buffer_manager_connector.cc",
+ "host/wayland_buffer_manager_connector.h",
+diff --git a/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc b/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc
+index 5d8167bdfd89..917f849811a2 100644
+--- a/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc
++++ b/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc
+@@ -126,10 +126,10 @@ bool GbmPixmapWayland::ScheduleOverlayPlane(
+ const gfx::RectF& crop_rect,
+ bool enable_blend,
+ std::unique_ptr<gfx::GpuFence> gpu_fence) {
+- auto* surface = buffer_manager_->GetSurface(widget);
+- DCHECK(surface);
++ auto surface_weak = buffer_manager_->GetSurface(widget);
++ DCHECK(surface_weak);
+ GbmSurfacelessWayland* surfaceless =
+- static_cast<GbmSurfacelessWayland*>(surface);
++ static_cast<GbmSurfacelessWayland*>(surface_weak.get());
+ DCHECK(surfaceless);
+
+ surfaceless->QueueOverlayPlane(
+diff --git a/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc b/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc
+index 70ea08acfa11..0554e772f5cb 100644
+--- a/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc
++++ b/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc
+@@ -34,7 +34,7 @@ GbmSurfacelessWayland::GbmSurfacelessWayland(
+ has_implicit_external_sync_(
+ HasEGLExtension("EGL_ARM_implicit_external_sync")),
+ weak_factory_(this) {
+- buffer_manager_->RegisterSurface(widget_, this);
++ buffer_manager_->RegisterSurface(widget_, GetWeakPtr());
+ unsubmitted_frames_.push_back(std::make_unique<PendingFrame>());
+ }
+
+diff --git a/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc b/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc
+index 63bfa3032fde..f113a9887bdc 100644
+--- a/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc
++++ b/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc
+@@ -43,19 +43,13 @@ void WaylandBufferManagerGpu::OnSubmission(gfx::AcceleratedWidget widget,
+ gfx::SwapResult swap_result) {
+ DCHECK(io_thread_runner_->BelongsToCurrentThread());
+ DCHECK_NE(widget, gfx::kNullAcceleratedWidget);
+- auto* surface = GetSurface(widget);
+- // There can be a race between destruction and submitting the last frames. The
+- // surface can be destroyed by the time the host receives a request to destroy
+- // a buffer, and is able to call the OnSubmission for that specific buffer.
+- if (surface) {
+- // As long as mojo calls rerouted to the IO child thread, we have to reroute
+- // them back to the same thread, where the original commit buffer call came
+- // from.
+- commit_thread_runner_->PostTask(
+- FROM_HERE,
+- base::Bind(&WaylandSurfaceGpu::OnSubmission, base::Unretained(surface),
+- buffer_id, swap_result));
+- }
++ auto surface = GetSurface(widget);
++ // As long as mojo calls rerouted to the IO child thread, we have to reroute
++ // them back to the same thread, where the original commit buffer call came
++ // from.
++ commit_thread_runner_->PostTask(
++ FROM_HERE, base::Bind(&WaylandSurfaceGpu::OnSubmission, surface,
++ buffer_id, swap_result));
+ }
+
+ void WaylandBufferManagerGpu::OnPresentation(
+@@ -64,36 +58,35 @@ void WaylandBufferManagerGpu::OnPresentation(
+ const gfx::PresentationFeedback& feedback) {
+ DCHECK(io_thread_runner_->BelongsToCurrentThread());
+ DCHECK_NE(widget, gfx::kNullAcceleratedWidget);
+- auto* surface = GetSurface(widget);
+- // There can be a race between destruction and presenting the last frames. The
+- // surface can be destroyed by the time the host receives a request to destroy
+- // a buffer, and is able to call the OnPresentation for that specific buffer.
+- if (surface) {
+- // As long as mojo calls rerouted to the IO child thread, we have to reroute
+- // them back to the same thread, where the original commit buffer call came
+- // from.
+- commit_thread_runner_->PostTask(
+- FROM_HERE, base::Bind(&WaylandSurfaceGpu::OnPresentation,
+- base::Unretained(surface), buffer_id, feedback));
+- }
+-}
+-
+-void WaylandBufferManagerGpu::RegisterSurface(gfx::AcceleratedWidget widget,
+- WaylandSurfaceGpu* surface) {
++ auto surface = GetSurface(widget);
++ // As long as mojo calls rerouted to the IO child thread, we have to reroute
++ // them back to the same thread, where the original commit buffer call came
++ // from.
++ commit_thread_runner_->PostTask(
++ FROM_HERE, base::Bind(&WaylandSurfaceGpu::OnPresentation, surface,
++ buffer_id, feedback));
++}
++
++void WaylandBufferManagerGpu::RegisterSurface(
++ gfx::AcceleratedWidget widget,
++ base::WeakPtr<WaylandSurfaceGpu> surface) {
++ base::AutoLock scoped_lock(lock_);
+ widget_to_surface_map_.insert(std::make_pair(widget, surface));
+ }
+
+ void WaylandBufferManagerGpu::UnregisterSurface(gfx::AcceleratedWidget widget) {
++ base::AutoLock scoped_lock(lock_);
+ widget_to_surface_map_.erase(widget);
+ }
+
+-WaylandSurfaceGpu* WaylandBufferManagerGpu::GetSurface(
+- gfx::AcceleratedWidget widget) const {
+- WaylandSurfaceGpu* surface = nullptr;
++base::WeakPtr<WaylandSurfaceGpu> WaylandBufferManagerGpu::GetSurface(
++ gfx::AcceleratedWidget widget) {
++ base::AutoLock scoped_lock(lock_);
++
+ auto it = widget_to_surface_map_.find(widget);
+ if (it != widget_to_surface_map_.end())
+- surface = it->second;
+- return surface;
++ return it->second;
++ return nullptr;
+ }
+
+ void WaylandBufferManagerGpu::CreateDmabufBasedBuffer(
+diff --git a/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h b/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h
+index 87439610cfc3..631d715e719e 100644
+--- a/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h
++++ b/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h
+@@ -8,6 +8,8 @@
+ #include <memory>
+
+ #include "base/macros.h"
++#include "base/memory/weak_ptr.h"
++#include "base/synchronization/lock.h"
+ #include "base/threading/sequenced_task_runner_handle.h"
+ #include "base/threading/thread_checker.h"
+ #include "mojo/public/cpp/bindings/associated_binding.h"
+@@ -64,9 +66,11 @@ class WaylandBufferManagerGpu : public ozone::mojom::WaylandBufferManagerGpu {
+ // result of the below operations, they must register themselves with the
+ // below APIs.
+ void RegisterSurface(gfx::AcceleratedWidget widget,
+- WaylandSurfaceGpu* surface);
++ base::WeakPtr<WaylandSurfaceGpu> surface);
+ void UnregisterSurface(gfx::AcceleratedWidget widget);
+- WaylandSurfaceGpu* GetSurface(gfx::AcceleratedWidget widget) const;
++ // A client of this method must always get and acquire lock before doing
++ // any manipulations with the surface. Once done, the lock must be released.
++ base::WeakPtr<WaylandSurfaceGpu> GetSurface(gfx::AcceleratedWidget widget);
+
+ // Methods, which can be used when in both in-process-gpu and out of process
+ // modes. These calls are forwarded to the browser process through the
+@@ -156,7 +160,8 @@ class WaylandBufferManagerGpu : public ozone::mojom::WaylandBufferManagerGpu {
+ mojo::AssociatedBinding<ozone::mojom::WaylandBufferManagerGpu>
+ associated_binding_;
+
+- std::map<gfx::AcceleratedWidget, WaylandSurfaceGpu*> widget_to_surface_map_;
++ std::map<gfx::AcceleratedWidget, base::WeakPtr<WaylandSurfaceGpu>>
++ widget_to_surface_map_; // Guarded by |lock_|.
+
+ // This task runner can be used to pass messages back to the same thread,
+ // where the commit buffer request came from. For example, swap requests come
+@@ -171,6 +176,9 @@ class WaylandBufferManagerGpu : public ozone::mojom::WaylandBufferManagerGpu {
+ // needed to ensure mojo calls happen on a right sequence.
+ scoped_refptr<base::SingleThreadTaskRunner> io_thread_runner_;
+
++ // Protects access to |widget_to_surface_map_|.
++ base::Lock lock_;
++
+ DISALLOW_COPY_AND_ASSIGN(WaylandBufferManagerGpu);
+ };
+
+diff --git a/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.cc b/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.cc
+index 6de24d7fd177..ce44ebac2915 100644
+--- a/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.cc
++++ b/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.cc
+@@ -29,7 +29,7 @@ WaylandCanvasSurface::WaylandCanvasSurface(
+ WaylandBufferManagerGpu* buffer_manager,
+ gfx::AcceleratedWidget widget)
+ : buffer_manager_(buffer_manager), widget_(widget) {
+- buffer_manager_->RegisterSurface(widget_, this);
++ buffer_manager_->RegisterSurface(widget_, GetWeakPtr());
+ }
+
+ WaylandCanvasSurface::~WaylandCanvasSurface() {
+diff --git a/ui/ozone/platform/wayland/gpu/wayland_surface_gpu.cc b/ui/ozone/platform/wayland/gpu/wayland_surface_gpu.cc
+new file mode 100644
+index 000000000000..85296edcca42
+--- /dev/null
++++ b/ui/ozone/platform/wayland/gpu/wayland_surface_gpu.cc
+@@ -0,0 +1,16 @@
++// Copyright 2019 The Chromium Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++
++#include "ui/ozone/platform/wayland/gpu/wayland_surface_gpu.h"
++
++namespace ui {
++
++WaylandSurfaceGpu::WaylandSurfaceGpu() = default;
++WaylandSurfaceGpu::~WaylandSurfaceGpu() = default;
++
++base::WeakPtr<WaylandSurfaceGpu> WaylandSurfaceGpu::GetWeakPtr() {
++ return weak_factory_.GetWeakPtr();
++}
++
++} // namespace ui
+diff --git a/ui/ozone/platform/wayland/gpu/wayland_surface_gpu.h b/ui/ozone/platform/wayland/gpu/wayland_surface_gpu.h
+index ace5279e838e..38d285317ab3 100644
+--- a/ui/ozone/platform/wayland/gpu/wayland_surface_gpu.h
++++ b/ui/ozone/platform/wayland/gpu/wayland_surface_gpu.h
+@@ -8,6 +8,7 @@
+ #include <memory>
+
+ #include "base/macros.h"
++#include "base/memory/weak_ptr.h"
+
+ namespace gfx {
+ enum class SwapResult;
+@@ -22,7 +23,7 @@ namespace ui {
+ // the buffer.
+ class WaylandSurfaceGpu {
+ public:
+- virtual ~WaylandSurfaceGpu() {}
++ virtual ~WaylandSurfaceGpu();
+
+ // Tells the surface the result of the last swap of buffer with the
+ // |buffer_id|.
+@@ -33,6 +34,16 @@ class WaylandSurfaceGpu {
+ // |buffer_id|.
+ virtual void OnPresentation(uint32_t buffer_id,
+ const gfx::PresentationFeedback& feedback) = 0;
++
++ protected:
++ WaylandSurfaceGpu();
++
++ base::WeakPtr<WaylandSurfaceGpu> GetWeakPtr();
++
++ private:
++ base::WeakPtrFactory<WaylandSurfaceGpu> weak_factory_{this};
++
++ DISALLOW_COPY_AND_ASSIGN(WaylandSurfaceGpu);
+ };
+
+ } // namespace ui
+--
+2.22.0
+