Commit 1e43916e authored by Maksim Sisov's avatar Maksim Sisov Committed by Commit Bot

ozone/wayland: Fix possible race with surfaces and buffers.

There is a possible race that results in a terminated gpu process.

That is, a surface may have been destroyed right before a request
that creates or commits buffers. To fix that, always create
buffers anonymously aka not attached to any surfaces, and simply
remove the pointer that the WaylandBufferManagerHost::Surface has
to the WaylandWindow so that it does not try to do anything except
the destruction of buffers, the call for which can come later
from the GPU process.

Bug: 1006813
Change-Id: I9f207ec8dac92b94a1e8f8b9fc9cd3fdb0186580
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1924247Reviewed-by: default avatarRobert Kroeger <rjkroege@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Commit-Queue: Maksim Sisov <msisov@igalia.com>
Cr-Commit-Position: refs/heads/master@{#718271}
parent e3604539
...@@ -203,7 +203,7 @@ void GbmPixmapWayland::CreateDmabufBasedBuffer() { ...@@ -203,7 +203,7 @@ void GbmPixmapWayland::CreateDmabufBasedBuffer() {
} }
// Asks Wayland to create a wl_buffer based on the |file| fd. // Asks Wayland to create a wl_buffer based on the |file| fd.
buffer_manager_->CreateDmabufBasedBuffer( buffer_manager_->CreateDmabufBasedBuffer(
widget_, std::move(fd), GetBufferSize(), strides, offsets, modifiers, std::move(fd), GetBufferSize(), strides, offsets, modifiers,
gbm_bo_->GetFormat(), plane_count, GetUniqueId()); gbm_bo_->GetFormat(), plane_count, GetUniqueId());
} }
......
...@@ -81,7 +81,6 @@ WaylandSurfaceGpu* WaylandBufferManagerGpu::GetSurface( ...@@ -81,7 +81,6 @@ WaylandSurfaceGpu* WaylandBufferManagerGpu::GetSurface(
} }
void WaylandBufferManagerGpu::CreateDmabufBasedBuffer( void WaylandBufferManagerGpu::CreateDmabufBasedBuffer(
gfx::AcceleratedWidget widget,
base::ScopedFD dmabuf_fd, base::ScopedFD dmabuf_fd,
gfx::Size size, gfx::Size size,
const std::vector<uint32_t>& strides, const std::vector<uint32_t>& strides,
...@@ -96,14 +95,13 @@ void WaylandBufferManagerGpu::CreateDmabufBasedBuffer( ...@@ -96,14 +95,13 @@ void WaylandBufferManagerGpu::CreateDmabufBasedBuffer(
io_thread_runner_->PostTask( io_thread_runner_->PostTask(
FROM_HERE, FROM_HERE,
base::BindOnce(&WaylandBufferManagerGpu::CreateDmabufBasedBufferInternal, base::BindOnce(&WaylandBufferManagerGpu::CreateDmabufBasedBufferInternal,
base::Unretained(this), widget, std::move(dmabuf_fd), base::Unretained(this), std::move(dmabuf_fd),
std::move(size), std::move(strides), std::move(offsets), std::move(size), std::move(strides), std::move(offsets),
std::move(modifiers), current_format, planes_count, std::move(modifiers), current_format, planes_count,
buffer_id)); buffer_id));
} }
void WaylandBufferManagerGpu::CreateShmBasedBuffer( void WaylandBufferManagerGpu::CreateShmBasedBuffer(
gfx::AcceleratedWidget widget,
base::ScopedFD shm_fd, base::ScopedFD shm_fd,
size_t length, size_t length,
gfx::Size size, gfx::Size size,
...@@ -114,7 +112,7 @@ void WaylandBufferManagerGpu::CreateShmBasedBuffer( ...@@ -114,7 +112,7 @@ void WaylandBufferManagerGpu::CreateShmBasedBuffer(
io_thread_runner_->PostTask( io_thread_runner_->PostTask(
FROM_HERE, FROM_HERE,
base::BindOnce(&WaylandBufferManagerGpu::CreateShmBasedBufferInternal, base::BindOnce(&WaylandBufferManagerGpu::CreateShmBasedBufferInternal,
base::Unretained(this), widget, std::move(shm_fd), length, base::Unretained(this), std::move(shm_fd), length,
std::move(size), buffer_id)); std::move(size), buffer_id));
} }
...@@ -160,7 +158,6 @@ WaylandBufferManagerGpu::GetModifiersForBufferFormat( ...@@ -160,7 +158,6 @@ WaylandBufferManagerGpu::GetModifiersForBufferFormat(
} }
void WaylandBufferManagerGpu::CreateDmabufBasedBufferInternal( void WaylandBufferManagerGpu::CreateDmabufBasedBufferInternal(
gfx::AcceleratedWidget widget,
base::ScopedFD dmabuf_fd, base::ScopedFD dmabuf_fd,
gfx::Size size, gfx::Size size,
const std::vector<uint32_t>& strides, const std::vector<uint32_t>& strides,
...@@ -172,14 +169,12 @@ void WaylandBufferManagerGpu::CreateDmabufBasedBufferInternal( ...@@ -172,14 +169,12 @@ void WaylandBufferManagerGpu::CreateDmabufBasedBufferInternal(
DCHECK(io_thread_runner_->BelongsToCurrentThread()); DCHECK(io_thread_runner_->BelongsToCurrentThread());
DCHECK(remote_host_); DCHECK(remote_host_);
remote_host_->CreateDmabufBasedBuffer( remote_host_->CreateDmabufBasedBuffer(
widget,
mojo::WrapPlatformHandle(mojo::PlatformHandle(std::move(dmabuf_fd))), mojo::WrapPlatformHandle(mojo::PlatformHandle(std::move(dmabuf_fd))),
size, strides, offsets, modifiers, current_format, planes_count, size, strides, offsets, modifiers, current_format, planes_count,
buffer_id); buffer_id);
} }
void WaylandBufferManagerGpu::CreateShmBasedBufferInternal( void WaylandBufferManagerGpu::CreateShmBasedBufferInternal(
gfx::AcceleratedWidget widget,
base::ScopedFD shm_fd, base::ScopedFD shm_fd,
size_t length, size_t length,
gfx::Size size, gfx::Size size,
...@@ -187,8 +182,8 @@ void WaylandBufferManagerGpu::CreateShmBasedBufferInternal( ...@@ -187,8 +182,8 @@ void WaylandBufferManagerGpu::CreateShmBasedBufferInternal(
DCHECK(io_thread_runner_->BelongsToCurrentThread()); DCHECK(io_thread_runner_->BelongsToCurrentThread());
DCHECK(remote_host_); DCHECK(remote_host_);
remote_host_->CreateShmBasedBuffer( remote_host_->CreateShmBasedBuffer(
widget, mojo::WrapPlatformHandle(mojo::PlatformHandle(std::move(shm_fd))), mojo::WrapPlatformHandle(mojo::PlatformHandle(std::move(shm_fd))), length,
length, size, buffer_id); size, buffer_id);
} }
void WaylandBufferManagerGpu::CommitBufferInternal( void WaylandBufferManagerGpu::CommitBufferInternal(
......
...@@ -75,8 +75,7 @@ class WaylandBufferManagerGpu : public ozone::mojom::WaylandBufferManagerGpu { ...@@ -75,8 +75,7 @@ class WaylandBufferManagerGpu : public ozone::mojom::WaylandBufferManagerGpu {
// ui/ozone/public/mojom/wayland/wayland_connection.mojom. // ui/ozone/public/mojom/wayland/wayland_connection.mojom.
// //
// Asks Wayland to create generic dmabuf-based wl_buffer. // Asks Wayland to create generic dmabuf-based wl_buffer.
void CreateDmabufBasedBuffer(gfx::AcceleratedWidget widget, void CreateDmabufBasedBuffer(base::ScopedFD dmabuf_fd,
base::ScopedFD dmabuf_fd,
gfx::Size size, gfx::Size size,
const std::vector<uint32_t>& strides, const std::vector<uint32_t>& strides,
const std::vector<uint32_t>& offsets, const std::vector<uint32_t>& offsets,
...@@ -86,8 +85,7 @@ class WaylandBufferManagerGpu : public ozone::mojom::WaylandBufferManagerGpu { ...@@ -86,8 +85,7 @@ class WaylandBufferManagerGpu : public ozone::mojom::WaylandBufferManagerGpu {
uint32_t buffer_id); uint32_t buffer_id);
// Asks Wayland to create a shared memory based wl_buffer. // Asks Wayland to create a shared memory based wl_buffer.
void CreateShmBasedBuffer(gfx::AcceleratedWidget widget, void CreateShmBasedBuffer(base::ScopedFD shm_fd,
base::ScopedFD shm_fd,
size_t length, size_t length,
gfx::Size size, gfx::Size size,
uint32_t buffer_id); uint32_t buffer_id);
...@@ -126,8 +124,7 @@ class WaylandBufferManagerGpu : public ozone::mojom::WaylandBufferManagerGpu { ...@@ -126,8 +124,7 @@ class WaylandBufferManagerGpu : public ozone::mojom::WaylandBufferManagerGpu {
gfx::BufferFormat buffer_format) const; gfx::BufferFormat buffer_format) const;
private: private:
void CreateDmabufBasedBufferInternal(gfx::AcceleratedWidget widget, void CreateDmabufBasedBufferInternal(base::ScopedFD dmabuf_fd,
base::ScopedFD dmabuf_fd,
gfx::Size size, gfx::Size size,
const std::vector<uint32_t>& strides, const std::vector<uint32_t>& strides,
const std::vector<uint32_t>& offsets, const std::vector<uint32_t>& offsets,
...@@ -135,8 +132,7 @@ class WaylandBufferManagerGpu : public ozone::mojom::WaylandBufferManagerGpu { ...@@ -135,8 +132,7 @@ class WaylandBufferManagerGpu : public ozone::mojom::WaylandBufferManagerGpu {
uint32_t current_format, uint32_t current_format,
uint32_t planes_count, uint32_t planes_count,
uint32_t buffer_id); uint32_t buffer_id);
void CreateShmBasedBufferInternal(gfx::AcceleratedWidget widget, void CreateShmBasedBufferInternal(base::ScopedFD shm_fd,
base::ScopedFD shm_fd,
size_t length, size_t length,
gfx::Size size, gfx::Size size,
uint32_t buffer_id); uint32_t buffer_id);
......
...@@ -78,9 +78,8 @@ class WaylandCanvasSurface::SharedMemoryBuffer { ...@@ -78,9 +78,8 @@ class WaylandCanvasSurface::SharedMemoryBuffer {
base::UnsafeSharedMemoryRegion::TakeHandleForSerialization( base::UnsafeSharedMemoryRegion::TakeHandleForSerialization(
std::move(shm_region)); std::move(shm_region));
base::subtle::ScopedFDPair fd_pair = platform_shm.PassPlatformHandle(); base::subtle::ScopedFDPair fd_pair = platform_shm.PassPlatformHandle();
buffer_manager_->CreateShmBasedBuffer(widget_, std::move(fd_pair.fd), buffer_manager_->CreateShmBasedBuffer(
checked_length.ValueOrDie(), size, std::move(fd_pair.fd), checked_length.ValueOrDie(), size, buffer_id_);
buffer_id_);
sk_surface_ = SkSurface::MakeRasterDirect( sk_surface_ = SkSurface::MakeRasterDirect(
SkImageInfo::MakeN32Premul(size.width(), size.height()), SkImageInfo::MakeN32Premul(size.width(), size.height()),
......
...@@ -117,8 +117,7 @@ class WaylandBufferManagerHost : public ozone::mojom::WaylandBufferManagerHost, ...@@ -117,8 +117,7 @@ class WaylandBufferManagerHost : public ozone::mojom::WaylandBufferManagerHost,
// Called by the GPU and asks to import a wl_buffer based on a gbm file // Called by the GPU and asks to import a wl_buffer based on a gbm file
// descriptor using zwp_linux_dmabuf protocol. Check comments in the // descriptor using zwp_linux_dmabuf protocol. Check comments in the
// ui/ozone/public/mojom/wayland/wayland_connection.mojom. // ui/ozone/public/mojom/wayland/wayland_connection.mojom.
void CreateDmabufBasedBuffer(gfx::AcceleratedWidget widget, void CreateDmabufBasedBuffer(mojo::ScopedHandle dmabuf_fd,
mojo::ScopedHandle dmabuf_fd,
const gfx::Size& size, const gfx::Size& size,
const std::vector<uint32_t>& strides, const std::vector<uint32_t>& strides,
const std::vector<uint32_t>& offsets, const std::vector<uint32_t>& offsets,
...@@ -129,8 +128,7 @@ class WaylandBufferManagerHost : public ozone::mojom::WaylandBufferManagerHost, ...@@ -129,8 +128,7 @@ class WaylandBufferManagerHost : public ozone::mojom::WaylandBufferManagerHost,
// Called by the GPU and asks to import a wl_buffer based on a shared memory // Called by the GPU and asks to import a wl_buffer based on a shared memory
// file descriptor using wl_shm protocol. Check comments in the // file descriptor using wl_shm protocol. Check comments in the
// ui/ozone/public/mojom/wayland/wayland_connection.mojom. // ui/ozone/public/mojom/wayland/wayland_connection.mojom.
void CreateShmBasedBuffer(gfx::AcceleratedWidget widget, void CreateShmBasedBuffer(mojo::ScopedHandle shm_fd,
mojo::ScopedHandle shm_fd,
uint64_t length, uint64_t length,
const gfx::Size& size, const gfx::Size& size,
uint32_t buffer_id) override; uint32_t buffer_id) override;
...@@ -160,16 +158,13 @@ class WaylandBufferManagerHost : public ozone::mojom::WaylandBufferManagerHost, ...@@ -160,16 +158,13 @@ class WaylandBufferManagerHost : public ozone::mojom::WaylandBufferManagerHost,
// presentation callbacks for that window's surface. // presentation callbacks for that window's surface.
class Surface; class Surface;
bool CreateBuffer(gfx::AcceleratedWidget& widget, bool CreateBuffer(const gfx::Size& size, uint32_t buffer_id);
const gfx::Size& size,
uint32_t buffer_id);
Surface* GetSurface(gfx::AcceleratedWidget widget) const; Surface* GetSurface(gfx::AcceleratedWidget widget) const;
// Validates data sent from GPU. If invalid, returns false and sets an error // Validates data sent from GPU. If invalid, returns false and sets an error
// message to |error_message_|. // message to |error_message_|.
bool ValidateDataFromGpu(const gfx::AcceleratedWidget& widget, bool ValidateDataFromGpu(const base::ScopedFD& file,
const base::ScopedFD& file,
const gfx::Size& size, const gfx::Size& size,
const std::vector<uint32_t>& strides, const std::vector<uint32_t>& strides,
const std::vector<uint32_t>& offsets, const std::vector<uint32_t>& offsets,
...@@ -177,18 +172,15 @@ class WaylandBufferManagerHost : public ozone::mojom::WaylandBufferManagerHost, ...@@ -177,18 +172,15 @@ class WaylandBufferManagerHost : public ozone::mojom::WaylandBufferManagerHost,
uint32_t format, uint32_t format,
uint32_t planes_count, uint32_t planes_count,
uint32_t buffer_id); uint32_t buffer_id);
bool ValidateDataFromGpu(const gfx::AcceleratedWidget& widget, bool ValidateBufferIdFromGpu(uint32_t buffer_id);
uint32_t buffer_id); bool ValidateDataFromGpu(const base::ScopedFD& file,
bool ValidateDataFromGpu(const gfx::AcceleratedWidget& widget,
const base::ScopedFD& file,
size_t length, size_t length,
const gfx::Size& size, const gfx::Size& size,
uint32_t buffer_id); uint32_t buffer_id);
// Callback method. Receives a result for the request to create a wl_buffer // Callback method. Receives a result for the request to create a wl_buffer
// backend by dmabuf file descriptor from ::CreateBuffer call. // backend by dmabuf file descriptor from ::CreateBuffer call.
void OnCreateBufferComplete(gfx::AcceleratedWidget widget, void OnCreateBufferComplete(uint32_t buffer_id,
uint32_t buffer_id,
wl::Object<struct wl_buffer> new_buffer); wl::Object<struct wl_buffer> new_buffer);
// Tells the |buffer_manager_gpu_ptr_| the result of a swap call and provides // Tells the |buffer_manager_gpu_ptr_| the result of a swap call and provides
...@@ -203,6 +195,8 @@ class WaylandBufferManagerHost : public ozone::mojom::WaylandBufferManagerHost, ...@@ -203,6 +195,8 @@ class WaylandBufferManagerHost : public ozone::mojom::WaylandBufferManagerHost,
// Terminates the GPU process on invalid data received // Terminates the GPU process on invalid data received
void TerminateGpuProcess(); void TerminateGpuProcess();
bool DestroyAnonymousBuffer(uint32_t buffer_id);
base::flat_map<gfx::AcceleratedWidget, std::unique_ptr<Surface>> surfaces_; base::flat_map<gfx::AcceleratedWidget, std::unique_ptr<Surface>> surfaces_;
// Set when invalid data is received from the GPU process. // Set when invalid data is received from the GPU process.
......
...@@ -22,18 +22,20 @@ interface WaylandBufferManagerHost { ...@@ -22,18 +22,20 @@ interface WaylandBufferManagerHost {
// The following two methods are used either for hardware accelerated // The following two methods are used either for hardware accelerated
// rendering or for the software rendering. // rendering or for the software rendering.
// //
// If hardware accelerated rendering path is taken, this methnod can be used // If the hardware accelerated rendering path is taken, this method can be
// to ask Wayland to create a wl_buffer based on the |dmabuf_fd| descriptor // used to ask Wayland to create a wl_buffer based on the |dmabuf_fd|
// for the WaylandWindow, which has the following |widget|. The |size| // descriptor. The |size| is the size of the buffer, the |strides|,
// is the size of the buffer, the |strides|, |offsets| and |modifiers| // |offsets| and |modifiers| are the descriptions of the drm buffer object.
// are the descriptions of the drm buffer object. The |format| describes // The |format| describes the buffer format (check gfx::BufferFormat) in
// the buffer format (check gfx::BufferFormat) in fourcc form. The // fourcc form. The |planes_count| says how many planes the buffer, backed
// |planes_count| says how many planes the buffer, backed by the |file| // by the |file| descriptor has. And the |buffer_id| is a unique id for the
// descriptor has. And the |buffer_id| is a unique id for the buffer, which // buffer, which is used to identify imported wl_buffers on the browser
// is used to identify imported wl_buffers on the browser process side and // process side and map them with the buffer objects on the gpu process side.
// map them with the buffer objects on the gpu process side. // The buffer will be associated with an AcceleratedWidget as soon as the
CreateDmabufBasedBuffer(gfx.mojom.AcceleratedWidget widget, // very first CommitBuffer request comes from viz to browser process.
handle dmabuf_fd, // If the buffer has been committed at least once, it is not possible to
// reassign it to another AcceleratedWidget.
CreateDmabufBasedBuffer(handle dmabuf_fd,
gfx.mojom.Size size, gfx.mojom.Size size,
array<uint32> strides, array<uint32> strides,
array<uint32> offsets, array<uint32> offsets,
...@@ -46,8 +48,11 @@ interface WaylandBufferManagerHost { ...@@ -46,8 +48,11 @@ interface WaylandBufferManagerHost {
// Wayland to create a wl_buffer based on the |shm_fd| descriptor. // Wayland to create a wl_buffer based on the |shm_fd| descriptor.
// The |length| is the length of the shared memory, |size| // The |length| is the length of the shared memory, |size|
// is the size of buffer and |buffer_id| is the id of the buffer. // is the size of buffer and |buffer_id| is the id of the buffer.
CreateShmBasedBuffer(gfx.mojom.AcceleratedWidget widget, // The buffer will be associated with an AcceleratedWidget as soon as the
handle shm_fd, // very first CommitBuffer request comes from viz to browser process. If
// the buffer has been committed at least once, it is not possible to
// reassign it to another AcceleratedWidget.
CreateShmBasedBuffer(handle shm_fd,
uint64 length, uint64 length,
gfx.mojom.Size size, gfx.mojom.Size size,
uint32 buffer_id); uint32 buffer_id);
...@@ -57,11 +62,14 @@ interface WaylandBufferManagerHost { ...@@ -57,11 +62,14 @@ interface WaylandBufferManagerHost {
// Destroys a wl_buffer created by WaylandConnection based on the |buffer_id| // Destroys a wl_buffer created by WaylandConnection based on the |buffer_id|
// for the WaylandWindow, which has the following |widget|. The |buffer_id| // for the WaylandWindow, which has the following |widget|. The |buffer_id|
// is the unique id of the buffer objects being destroyed on the browser // is the unique id of the buffer objects being destroyed on the browser
// process side. // process side. If the buffer with |buffer_id| has never been assigned to an
// AcceleratedWidget, it can be destroyed by passing a null widget
// with a correct buffer id. Providing wrong pair of the |widget| and the
// |buffer_id| will result in the termination of the GPU process.
DestroyBuffer(gfx.mojom.AcceleratedWidget widget, uint32 buffer_id); DestroyBuffer(gfx.mojom.AcceleratedWidget widget, uint32 buffer_id);
// Attaches a wl_buffer to a WaylandWindow's surface with the following // Attaches a wl_buffer to a WaylandWindow's surface with the following
// |widget|. The |damage_region| describes changed the region of the buffer. // |widget|. The |damage_region| describes the changed region of the buffer.
// The |buffer_id| is a unique id for the buffer, which is used to // The |buffer_id| is a unique id for the buffer, which is used to
// identify imported wl_buffers on the browser process side mapped with // identify imported wl_buffers on the browser process side mapped with
// the ones on the gpu process. // the ones on the gpu process.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment