Stop crashing after process swap

This commit is contained in:
Michael Catanzaro 2021-04-17 08:20:39 -05:00
parent cf71752886
commit 1b26ebec47
13 changed files with 1131 additions and 1 deletions

View File

@ -0,0 +1,76 @@
From 951ce45d4c229a4f6abea39acd4f7dc759d9ef10 Mon Sep 17 00:00:00 2001
From: Michael Catanzaro <mcatanzaro@gnome.org>
Date: Fri, 9 Apr 2021 13:10:02 -0500
Subject: [PATCH 01/13] Add some checks to ensure we properly bind server
globals
If we fail to bind any global objects, we are going to crash. Let's do
that as nicely as possible using g_error(), rather than dereferencing
null pointers later on.
Suggested by #145
(cherry picked from commit a4eb79d12fc851ea7cef616afa0d77668e83ea61)
---
src/extensions/audio.cpp | 3 +++
src/extensions/video-plane-display-dmabuf.cpp | 3 +++
src/ws-client.cpp | 8 ++++++++
3 files changed, 14 insertions(+)
diff --git a/src/extensions/audio.cpp b/src/extensions/audio.cpp
index b3043ac..5d2dd91 100644
--- a/src/extensions/audio.cpp
+++ b/src/extensions/audio.cpp
@@ -159,6 +159,9 @@ public:
wl_display_roundtrip_queue(display, eventQueue);
wl_registry_destroy(registry);
+ if (!m_wl.audio)
+ g_error("Failed to bind wpe_audio");
+
wl_event_queue_destroy(eventQueue);
}
diff --git a/src/extensions/video-plane-display-dmabuf.cpp b/src/extensions/video-plane-display-dmabuf.cpp
index 953cb4c..96fabcf 100644
--- a/src/extensions/video-plane-display-dmabuf.cpp
+++ b/src/extensions/video-plane-display-dmabuf.cpp
@@ -159,6 +159,9 @@ public:
wl_display_roundtrip_queue(display, eventQueue);
wl_registry_destroy(registry);
+ if (!m_wl.videoPlaneDisplayDmaBuf)
+ g_error("Failed to bind wpe_video_plane_display_dmabuf");
+
wl_event_queue_destroy(eventQueue);
}
diff --git a/src/ws-client.cpp b/src/ws-client.cpp
index 6dc98ca..4ffa090 100644
--- a/src/ws-client.cpp
+++ b/src/ws-client.cpp
@@ -126,6 +126,9 @@ BaseBackend::BaseBackend(int hostFD)
wl_display_roundtrip(m_wl.display);
wl_registry_destroy(registry);
+ if (!m_wl.wpeBridge)
+ g_error("Failed to bind wpe_bridge");
+
wpe_bridge_add_listener(m_wl.wpeBridge, &s_bridgeListener, this);
wpe_bridge_initialize(m_wl.wpeBridge);
wl_display_roundtrip(m_wl.display);
@@ -204,6 +207,11 @@ void BaseTarget::initialize(BaseBackend& backend)
wl_display_roundtrip_queue(display, m_wl.eventQueue);
wl_registry_destroy(registry);
+ if (!m_wl.compositor)
+ g_error("Failed to bind wl_compositor");
+ if (!m_wl.wpeBridge)
+ g_error("Failed to bind wpe_bridge");
+
m_wl.surface = wl_compositor_create_surface(m_wl.compositor);
wl_proxy_set_queue(reinterpret_cast<struct wl_proxy*>(m_wl.surface), m_wl.eventQueue);
--
2.31.1

View File

@ -0,0 +1,63 @@
From 6963a05959d8be52d4b8ee0cafc49da72a04a6dd Mon Sep 17 00:00:00 2001
From: Adrian Perez de Castro <aperez@igalia.com>
Date: Tue, 13 Apr 2021 00:30:08 +0300
Subject: [PATCH 02/13] ws: Remove unneeded Surface::id member
The Wayland resource identifier is not used at the moment, and moreover
if ever needed wl_resource_get_id(surface->bufferResource) can be used
to retrieve it.
(cherry picked from commit 55d05be5529635b7797f34b3e9871612909859fc)
---
src/ws.cpp | 6 ++----
src/ws.h | 9 ++++++---
2 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/src/ws.cpp b/src/ws.cpp
index 5602595..c23e53c 100644
--- a/src/ws.cpp
+++ b/src/ws.cpp
@@ -144,9 +144,7 @@ static const struct wl_compositor_interface s_compositorInterface = {
return;
}
- auto* surface = new Surface;
- surface->client = client;
- surface->id = id;
+ auto* surface = new Surface {surfaceResource};
wl_resource_set_implementation(surfaceResource, &s_surfaceInterface, surface,
[](struct wl_resource* resource)
{
@@ -524,7 +522,7 @@ struct wl_client* Instance::registerViewBackend(uint32_t surfaceId, APIClient& a
g_error("Instance::registerViewBackend(): " "Cannot find surface %" PRIu32 " in view backend map.", surfaceId);
it->second->apiClient = &apiClient;
- return it->second->client;
+ return wl_resource_get_client(it->second->resource);
}
void Instance::unregisterViewBackend(uint32_t surfaceId)
diff --git a/src/ws.h b/src/ws.h
index d4376c4..683b679 100644
--- a/src/ws.h
+++ b/src/ws.h
@@ -48,10 +48,13 @@ struct APIClient {
virtual void exportEGLStreamProducer(struct wl_resource*) = 0;
};
-struct Surface;
struct Surface {
- uint32_t id { 0 };
- struct wl_client* client { nullptr };
+ explicit Surface(struct wl_resource* surfaceResource):
+ resource {surfaceResource}
+ {
+ }
+
+ struct wl_resource* resource;
APIClient* apiClient { nullptr };
--
2.31.1

View File

@ -0,0 +1,135 @@
From 2722e7369ae746cc71604bcd13e1f4c6dd5816c3 Mon Sep 17 00:00:00 2001
From: Adrian Perez de Castro <aperez@igalia.com>
Date: Tue, 13 Apr 2021 01:06:41 +0300
Subject: [PATCH 03/13] ws: Rename surfaceId to bridgeId where appropriate
The fact is that WS::Instance::m_viewBackendMap associated wpe_bridge
identifiers with a Surface, therefore it is clearer when reading the
code to name variables accordingly.
(cherry picked from commit 2d58520c94cd1c06d940621acaf409480ef908e8)
---
src/view-backend-private.cpp | 23 +++++++++++------------
src/view-backend-private.h | 2 +-
src/ws.cpp | 10 +++++-----
src/ws.h | 1 +
4 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/src/view-backend-private.cpp b/src/view-backend-private.cpp
index 78f0e2f..367e6c3 100644
--- a/src/view-backend-private.cpp
+++ b/src/view-backend-private.cpp
@@ -41,7 +41,7 @@ ViewBackend::ViewBackend(ClientBundle* clientBundle, struct wpe_view_backend* ba
ViewBackend::~ViewBackend()
{
- unregisterSurface(m_surfaceId);
+ unregisterSurface(m_bridgeId);
if (m_clientFd != -1)
close(m_clientFd);
}
@@ -131,29 +131,28 @@ void ViewBackend::clientDestroyNotify(struct wl_listener* listener, void*)
ViewBackend* self = wl_container_of(listener, self, m_clientDestroy);
self->clearFrameCallbacks();
- WS::Instance::singleton().unregisterViewBackend(self->m_surfaceId);
+ WS::Instance::singleton().unregisterViewBackend(self->m_bridgeId);
self->m_client = nullptr;
- self->m_surfaceId = 0;
+ self->m_bridgeId = 0;
wl_list_remove(&self->m_clientDestroy.link);
}
-void ViewBackend::registerSurface(uint32_t surfaceId)
+void ViewBackend::registerSurface(uint32_t bridgeId)
{
-
- if (m_surfaceId == surfaceId)
+ if (m_bridgeId == bridgeId)
return;
- unregisterSurface(m_surfaceId);
+ unregisterSurface(m_bridgeId);
- m_surfaceId = surfaceId;
- m_client = WS::Instance::singleton().registerViewBackend(m_surfaceId, *this);
+ m_bridgeId = bridgeId;
+ m_client = WS::Instance::singleton().registerViewBackend(m_bridgeId, *this);
wl_client_add_destroy_listener(m_client, &m_clientDestroy);
}
-void ViewBackend::unregisterSurface(uint32_t surfaceId)
+void ViewBackend::unregisterSurface(uint32_t bridgeId)
{
- if (!surfaceId || m_surfaceId != surfaceId)
+ if (!bridgeId || m_bridgeId != bridgeId)
return;
// If the surfaceId is valid, we cannot have an invalid wl_client.
@@ -165,7 +164,7 @@ void ViewBackend::unregisterSurface(uint32_t surfaceId)
// After destroying the client, none of these can be valid.
g_assert(m_client == nullptr);
- g_assert(m_surfaceId == 0);
+ g_assert(m_bridgeId == 0);
}
void ViewBackend::didReceiveMessage(uint32_t messageId, uint32_t messageBody)
diff --git a/src/view-backend-private.h b/src/view-backend-private.h
index 918ec0e..9500262 100644
--- a/src/view-backend-private.h
+++ b/src/view-backend-private.h
@@ -90,7 +90,7 @@ private:
static gboolean s_socketCallback(GSocket*, GIOCondition, gpointer);
- uint32_t m_surfaceId { 0 };
+ uint32_t m_bridgeId { 0 };
static void clientDestroyNotify(struct wl_listener*, void*);
struct wl_listener m_clientDestroy { {}, clientDestroyNotify };
diff --git a/src/ws.cpp b/src/ws.cpp
index c23e53c..a044b2e 100644
--- a/src/ws.cpp
+++ b/src/ws.cpp
@@ -515,19 +515,19 @@ void Instance::releaseAudioPacketExport(struct wpe_audio_packet_export* packet_e
wpe_audio_packet_export_send_release(packet_export->exportResource);
}
-struct wl_client* Instance::registerViewBackend(uint32_t surfaceId, APIClient& apiClient)
+struct wl_client* Instance::registerViewBackend(uint32_t bridgeId, APIClient& apiClient)
{
- auto it = m_viewBackendMap.find(surfaceId);
+ auto it = m_viewBackendMap.find(bridgeId);
if (it == m_viewBackendMap.end())
- g_error("Instance::registerViewBackend(): " "Cannot find surface %" PRIu32 " in view backend map.", surfaceId);
+ g_error("Instance::registerViewBackend(): " "Cannot find surface with bridgeId %" PRIu32 " in view backend map.", bridgeId);
it->second->apiClient = &apiClient;
return wl_resource_get_client(it->second->resource);
}
-void Instance::unregisterViewBackend(uint32_t surfaceId)
+void Instance::unregisterViewBackend(uint32_t bridgeId)
{
- auto it = m_viewBackendMap.find(surfaceId);
+ auto it = m_viewBackendMap.find(bridgeId);
if (it != m_viewBackendMap.end()) {
it->second->apiClient = nullptr;
m_viewBackendMap.erase(it);
diff --git a/src/ws.h b/src/ws.h
index 683b679..aa0c083 100644
--- a/src/ws.h
+++ b/src/ws.h
@@ -128,6 +128,7 @@ private:
struct wl_global* m_wpeBridge { nullptr };
GSource* m_source { nullptr };
+ // (bridgeId -> Surface)
std::unordered_map<uint32_t, Surface*> m_viewBackendMap;
struct {
--
2.31.1

View File

@ -0,0 +1,262 @@
From 98ad602e5f5d51162ec715a023b87d06a71d627b Mon Sep 17 00:00:00 2001
From: Adrian Perez de Castro <aperez@igalia.com>
Date: Thu, 8 Apr 2021 00:57:49 +0300
Subject: [PATCH 04/13] ws: Accumulate surface frame callbacks until commit
Move code around to accumulate surface frame callback additions until
changes are comitted to the surface, as intended according to the base
Wayland protocol specification.
As a bonus, remove the auxiliar ViewBackend::FrameCallbackResource
by passing a destruction callback to wl_resource_set_implementation()
and using the internal wl_resource list link.
(cherry picked from commit 3ab4a3c9770d333ebbc65ab42a604836c6da57ec)
---
src/view-backend-private.cpp | 45 ++----------------------------------
src/view-backend-private.h | 14 -----------
src/ws.cpp | 19 +++++++++++++--
src/ws.h | 39 ++++++++++++++++++++++++++++++-
4 files changed, 57 insertions(+), 60 deletions(-)
diff --git a/src/view-backend-private.cpp b/src/view-backend-private.cpp
index 367e6c3..f04a57e 100644
--- a/src/view-backend-private.cpp
+++ b/src/view-backend-private.cpp
@@ -35,7 +35,6 @@ ViewBackend::ViewBackend(ClientBundle* clientBundle, struct wpe_view_backend* ba
{
m_clientBundle->viewBackend = this;
- wl_list_init(&m_frameCallbacks);
wl_list_init(&m_clientDestroy.link);
}
@@ -72,15 +71,6 @@ int ViewBackend::clientFd()
return dup(m_clientFd);
}
-void ViewBackend::frameCallback(struct wl_resource* callback)
-{
- auto* resource = new FrameCallbackResource;
- resource->resource = callback;
- resource->destroyListener.notify = FrameCallbackResource::destroyNotify;
- wl_resource_add_destroy_listener(callback, &resource->destroyListener);
- wl_list_insert(&m_frameCallbacks, &resource->link);
-}
-
void ViewBackend::exportBufferResource(struct wl_resource* bufferResource)
{
m_clientBundle->exportBuffer(bufferResource);
@@ -103,16 +93,8 @@ void ViewBackend::exportEGLStreamProducer(struct wl_resource* bufferResource)
void ViewBackend::dispatchFrameCallbacks()
{
- if (G_UNLIKELY(!m_client))
- return;
-
- FrameCallbackResource* resource;
- wl_list_for_each(resource, &m_frameCallbacks, link) {
- wl_callback_send_done(resource->resource, 0);
- }
- clearFrameCallbacks();
-
- wl_client_flush(m_client);
+ if (G_LIKELY(m_bridgeId))
+ WS::Instance::singleton().dispatchFrameCallbacks(m_bridgeId);
wpe_view_backend_dispatch_frame_displayed(m_backend);
}
@@ -130,7 +112,6 @@ void ViewBackend::clientDestroyNotify(struct wl_listener* listener, void*)
{
ViewBackend* self = wl_container_of(listener, self, m_clientDestroy);
- self->clearFrameCallbacks();
WS::Instance::singleton().unregisterViewBackend(self->m_bridgeId);
self->m_client = nullptr;
self->m_bridgeId = 0;
@@ -180,25 +161,3 @@ void ViewBackend::didReceiveMessage(uint32_t messageId, uint32_t messageBody)
assert(!"WPE fdo received an invalid IPC message");
}
}
-
-void ViewBackend::clearFrameCallbacks()
-{
- FrameCallbackResource* resource;
- FrameCallbackResource* next;
- wl_list_for_each_safe(resource, next, &m_frameCallbacks, link) {
- wl_list_remove(&resource->link);
- wl_list_remove(&resource->destroyListener.link);
- wl_resource_destroy(resource->resource);
- delete resource;
- }
- wl_list_init(&m_frameCallbacks);
-}
-
-void ViewBackend::FrameCallbackResource::destroyNotify(struct wl_listener* listener, void*)
-{
- FrameCallbackResource* resource;
- resource = wl_container_of(listener, resource, destroyListener);
-
- wl_list_remove(&resource->link);
- delete resource;
-}
diff --git a/src/view-backend-private.h b/src/view-backend-private.h
index 9500262..a598dee 100644
--- a/src/view-backend-private.h
+++ b/src/view-backend-private.h
@@ -63,7 +63,6 @@ public:
void initialize();
int clientFd();
- void frameCallback(struct wl_resource* callbackResource) override;
void exportBufferResource(struct wl_resource* bufferResource) override;
void exportLinuxDmabuf(const struct linux_dmabuf_buffer *dmabuf_buffer) override;
void exportShmBuffer(struct wl_resource* bufferResource, struct wl_shm_buffer* shmBuffer) override;
@@ -72,22 +71,11 @@ public:
void releaseBuffer(struct wl_resource* buffer_resource);
private:
- struct FrameCallbackResource {
- struct wl_resource* resource;
-
- struct wl_list link;
- struct wl_listener destroyListener;
-
- static void destroyNotify(struct wl_listener*, void*);
- };
-
void didReceiveMessage(uint32_t messageId, uint32_t messageBody) override;
void registerSurface(uint32_t);
void unregisterSurface(uint32_t);
- void clearFrameCallbacks();
-
static gboolean s_socketCallback(GSocket*, GIOCondition, gpointer);
uint32_t m_bridgeId { 0 };
@@ -99,8 +87,6 @@ private:
ClientBundle* m_clientBundle;
struct wpe_view_backend* m_backend;
- struct wl_list m_frameCallbacks;
-
std::unique_ptr<FdoIPC::Connection> m_socket;
int m_clientFd { -1 };
};
diff --git a/src/ws.cpp b/src/ws.cpp
index a044b2e..87faaf3 100644
--- a/src/ws.cpp
+++ b/src/ws.cpp
@@ -110,8 +110,11 @@ static const struct wl_surface_interface s_surfaceInterface = {
return;
}
- wl_resource_set_implementation(callbackResource, nullptr, nullptr, nullptr);
- surface.apiClient->frameCallback(callbackResource);
+ wl_resource_set_implementation(callbackResource, nullptr, nullptr,
+ [](struct wl_resource* resource) {
+ wl_list_remove(wl_resource_get_link(resource));
+ });
+ surface.addFrameCallback(callbackResource);
},
// set_opaque_region
[](struct wl_client*, struct wl_resource*, struct wl_resource*) { },
@@ -121,6 +124,7 @@ static const struct wl_surface_interface s_surfaceInterface = {
[](struct wl_client*, struct wl_resource* surfaceResource)
{
auto& surface = *static_cast<Surface*>(wl_resource_get_user_data(surfaceResource));
+ surface.commit();
WS::Instance::singleton().impl().surfaceCommit(surface);
},
// set_buffer_transform
@@ -534,4 +538,15 @@ void Instance::unregisterViewBackend(uint32_t bridgeId)
}
}
+void Instance::dispatchFrameCallbacks(uint32_t bridgeId)
+{
+ auto it = m_viewBackendMap.find(bridgeId);
+ if (it == m_viewBackendMap.end()) {
+ g_error("Instance::dispatchFrameCallbacks(): "
+ "Cannot find surface with bridgeId %" PRIu32 " in view backend map.", bridgeId);
+ }
+
+ it->second->dispatchFrameCallbacks();
+}
+
} // namespace WS
diff --git a/src/ws.h b/src/ws.h
index aa0c083..30baf8e 100644
--- a/src/ws.h
+++ b/src/ws.h
@@ -41,7 +41,6 @@ namespace WS {
struct APIClient {
virtual ~APIClient() = default;
- virtual void frameCallback(struct wl_resource*) = 0;
virtual void exportBufferResource(struct wl_resource*) = 0;
virtual void exportLinuxDmabuf(const struct linux_dmabuf_buffer *dmabuf_buffer) = 0;
virtual void exportShmBuffer(struct wl_resource*, struct wl_shm_buffer*) = 0;
@@ -52,6 +51,18 @@ struct Surface {
explicit Surface(struct wl_resource* surfaceResource):
resource {surfaceResource}
{
+ wl_list_init(&m_pendingFrameCallbacks);
+ wl_list_init(&m_currentFrameCallbacks);
+ }
+
+ ~Surface()
+ {
+ struct wl_resource* resource;
+ struct wl_resource* tmp;
+ wl_resource_for_each_safe(resource, tmp, &m_pendingFrameCallbacks)
+ wl_resource_destroy(resource);
+ wl_resource_for_each_safe(resource, tmp, &m_currentFrameCallbacks)
+ wl_resource_destroy(resource);
}
struct wl_resource* resource;
@@ -61,6 +72,31 @@ struct Surface {
struct wl_resource* bufferResource { nullptr };
const struct linux_dmabuf_buffer* dmabufBuffer { nullptr };
struct wl_shm_buffer* shmBuffer { nullptr };
+
+ void commit()
+ {
+ wl_list_insert_list(&m_currentFrameCallbacks, &m_pendingFrameCallbacks);
+ wl_list_init(&m_pendingFrameCallbacks);
+ }
+
+ void addFrameCallback(struct wl_resource* resource)
+ {
+ wl_list_insert(m_pendingFrameCallbacks.prev, wl_resource_get_link(resource));
+ }
+
+ void dispatchFrameCallbacks()
+ {
+ struct wl_resource* resource;
+ struct wl_resource* tmp;
+ wl_resource_for_each_safe(resource, tmp, &m_currentFrameCallbacks) {
+ wl_callback_send_done(resource, 0);
+ wl_resource_destroy(resource);
+ }
+ }
+
+private:
+ struct wl_list m_pendingFrameCallbacks;
+ struct wl_list m_currentFrameCallbacks;
};
class Instance {
@@ -95,6 +131,7 @@ public:
void registerSurface(uint32_t, Surface*);
struct wl_client* registerViewBackend(uint32_t, APIClient&);
void unregisterViewBackend(uint32_t);
+ void dispatchFrameCallbacks(uint32_t);
using VideoPlaneDisplayDmaBufCallback = std::function<void(struct wpe_video_plane_display_dmabuf_export*, uint32_t, int, int32_t, int32_t, int32_t, int32_t, uint32_t)>;
using VideoPlaneDisplayDmaBufEndOfStreamCallback = std::function<void(uint32_t)>;
--
2.31.1

View File

@ -0,0 +1,29 @@
From 89e4b1683ad51c1b066fc10c748e5d524fb37cd2 Mon Sep 17 00:00:00 2001
From: Adrian Perez de Castro <aperez@igalia.com>
Date: Wed, 14 Apr 2021 21:56:12 +0300
Subject: [PATCH 06/13] meson: Make scripts/version.py work with older Pythons
Older Python versions (3.5, 2.x) do not have a __getitem__ method
on regex match objects, so use the .group() method instead, which is
available in all versions.
(cherry picked from commit 8c4b29f973500a9a596e27a2b3042923e4c905f7)
---
scripts/version.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/version.py b/scripts/version.py
index 1dbbdb3..e2af013 100644
--- a/scripts/version.py
+++ b/scripts/version.py
@@ -18,6 +18,6 @@ with open(version_file, "r") as f:
for line in f.readlines():
m = version_re.match(line)
if m:
- version[m[1]] = m[2]
+ version[m.group(1)] = m.group(2)
print("{}.{}.{}".format(version["MAJOR"], version["MINOR"], version["MICRO"]))
--
2.31.1

View File

@ -0,0 +1,132 @@
From 4657edaf9f798863d16d94e61a3f467ee656e908 Mon Sep 17 00:00:00 2001
From: Adrian Perez de Castro <aperez@igalia.com>
Date: Sat, 10 Apr 2021 18:27:42 +0300
Subject: [PATCH 07/13] Revert "view backend: Properly unregister surfaces"
This reverts commit 99bd04019800f84a722ae99bf1a352f225d93002.
---
src/view-backend-private.cpp | 52 +++++++++++++-----------------------
src/view-backend-private.h | 8 +++---
2 files changed, 24 insertions(+), 36 deletions(-)
diff --git a/src/view-backend-private.cpp b/src/view-backend-private.cpp
index f04a57e..4920037 100644
--- a/src/view-backend-private.cpp
+++ b/src/view-backend-private.cpp
@@ -34,13 +34,12 @@ ViewBackend::ViewBackend(ClientBundle* clientBundle, struct wpe_view_backend* ba
, m_backend(backend)
{
m_clientBundle->viewBackend = this;
-
- wl_list_init(&m_clientDestroy.link);
}
ViewBackend::~ViewBackend()
{
unregisterSurface(m_bridgeId);
+
if (m_clientFd != -1)
close(m_clientFd);
}
@@ -96,39 +95,24 @@ void ViewBackend::dispatchFrameCallbacks()
if (G_LIKELY(m_bridgeId))
WS::Instance::singleton().dispatchFrameCallbacks(m_bridgeId);
+ if (m_client.object)
+ wl_client_flush(m_client.object);
wpe_view_backend_dispatch_frame_displayed(m_backend);
}
void ViewBackend::releaseBuffer(struct wl_resource* buffer_resource)
{
- if (G_UNLIKELY(!m_client))
- return;
-
wl_buffer_send_release(buffer_resource);
- wl_client_flush(m_client);
-}
-
-void ViewBackend::clientDestroyNotify(struct wl_listener* listener, void*)
-{
- ViewBackend* self = wl_container_of(listener, self, m_clientDestroy);
-
- WS::Instance::singleton().unregisterViewBackend(self->m_bridgeId);
- self->m_client = nullptr;
- self->m_bridgeId = 0;
-
- wl_list_remove(&self->m_clientDestroy.link);
+ if (m_client.object)
+ wl_client_flush(m_client.object);
}
void ViewBackend::registerSurface(uint32_t bridgeId)
{
- if (m_bridgeId == bridgeId)
- return;
-
- unregisterSurface(m_bridgeId);
-
m_bridgeId = bridgeId;
- m_client = WS::Instance::singleton().registerViewBackend(m_bridgeId, *this);
- wl_client_add_destroy_listener(m_client, &m_clientDestroy);
+ m_client.object = WS::Instance::singleton().registerViewBackend(m_bridgeId, *this);
+ m_client.destroyListener.notify = Client::destroyNotify;
+ wl_client_add_destroy_listener(m_client.object, &m_client.destroyListener);
}
void ViewBackend::unregisterSurface(uint32_t bridgeId)
@@ -136,16 +120,10 @@ void ViewBackend::unregisterSurface(uint32_t bridgeId)
if (!bridgeId || m_bridgeId != bridgeId)
return;
- // If the surfaceId is valid, we cannot have an invalid wl_client.
- g_assert(m_client != nullptr);
-
- // Destroying the client triggers the m_clientDestroy callback,
- // the rest of the teardown is done from there.
- wl_client_destroy(m_client);
+ g_clear_pointer(&m_client.object, wl_client_destroy);
- // After destroying the client, none of these can be valid.
- g_assert(m_client == nullptr);
- g_assert(m_bridgeId == 0);
+ WS::Instance::singleton().unregisterViewBackend(m_bridgeId);
+ m_bridgeId = 0;
}
void ViewBackend::didReceiveMessage(uint32_t messageId, uint32_t messageBody)
@@ -161,3 +139,11 @@ void ViewBackend::didReceiveMessage(uint32_t messageId, uint32_t messageBody)
assert(!"WPE fdo received an invalid IPC message");
}
}
+
+void ViewBackend::Client::destroyNotify(struct wl_listener* listener, void*)
+{
+ Client* client;
+ client = wl_container_of(listener, client, destroyListener);
+
+ client->object = nullptr;
+}
diff --git a/src/view-backend-private.h b/src/view-backend-private.h
index a598dee..37eab08 100644
--- a/src/view-backend-private.h
+++ b/src/view-backend-private.h
@@ -79,10 +79,12 @@ private:
static gboolean s_socketCallback(GSocket*, GIOCondition, gpointer);
uint32_t m_bridgeId { 0 };
+ struct Client {
+ struct wl_client* object { nullptr };
+ struct wl_listener destroyListener;
- static void clientDestroyNotify(struct wl_listener*, void*);
- struct wl_listener m_clientDestroy { {}, clientDestroyNotify };
- struct wl_client* m_client { nullptr };
+ static void destroyNotify(struct wl_listener*, void*);
+ } m_client;
ClientBundle* m_clientBundle;
struct wpe_view_backend* m_backend;
--
2.31.1

View File

@ -0,0 +1,40 @@
From 00a6f6d61cb20af45714360bf458348aeaf08751 Mon Sep 17 00:00:00 2001
From: Adrian Perez de Castro <aperez@igalia.com>
Date: Sat, 10 Apr 2021 18:27:55 +0300
Subject: [PATCH 08/13] Revert "view-backend-private: Move wl_client_destroy to
unregisterSurface()"
This reverts commit f54135e65a6894bdf509153d2f6e96a627352306.
---
src/view-backend-private.cpp | 2 --
src/ws.cpp | 1 +
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/view-backend-private.cpp b/src/view-backend-private.cpp
index 4920037..e1554bb 100644
--- a/src/view-backend-private.cpp
+++ b/src/view-backend-private.cpp
@@ -120,8 +120,6 @@ void ViewBackend::unregisterSurface(uint32_t bridgeId)
if (!bridgeId || m_bridgeId != bridgeId)
return;
- g_clear_pointer(&m_client.object, wl_client_destroy);
-
WS::Instance::singleton().unregisterViewBackend(m_bridgeId);
m_bridgeId = 0;
}
diff --git a/src/ws.cpp b/src/ws.cpp
index 87faaf3..80cb39b 100644
--- a/src/ws.cpp
+++ b/src/ws.cpp
@@ -534,6 +534,7 @@ void Instance::unregisterViewBackend(uint32_t bridgeId)
auto it = m_viewBackendMap.find(bridgeId);
if (it != m_viewBackendMap.end()) {
it->second->apiClient = nullptr;
+ wl_client_destroy(wl_resource_get_client(it->second->resource));
m_viewBackendMap.erase(it);
}
}
--
2.31.1

View File

@ -0,0 +1,26 @@
From 542587bae6b894bdd1a5cfd38223f8054d166fc3 Mon Sep 17 00:00:00 2001
From: Adrian Perez de Castro <aperez@igalia.com>
Date: Sat, 10 Apr 2021 18:28:43 +0300
Subject: [PATCH 09/13] Revert "ws: Call wl_client_destroy for the created
wl_client in Instance::unregisterViewBackend()"
This reverts commit 9a0e6cb62bfae44ef3496d950899ecb34ddd24a5.
---
src/ws.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/ws.cpp b/src/ws.cpp
index 80cb39b..87faaf3 100644
--- a/src/ws.cpp
+++ b/src/ws.cpp
@@ -534,7 +534,6 @@ void Instance::unregisterViewBackend(uint32_t bridgeId)
auto it = m_viewBackendMap.find(bridgeId);
if (it != m_viewBackendMap.end()) {
it->second->apiClient = nullptr;
- wl_client_destroy(wl_resource_get_client(it->second->resource));
m_viewBackendMap.erase(it);
}
}
--
2.31.1

101
0010-Revert-Cleanups.patch Normal file
View File

@ -0,0 +1,101 @@
From 18244c702bba27d32a022bd8a2ff9269fcb18cc5 Mon Sep 17 00:00:00 2001
From: Adrian Perez de Castro <aperez@igalia.com>
Date: Sat, 10 Apr 2021 18:29:05 +0300
Subject: [PATCH 10/13] Revert "Cleanups."
This reverts commit 9e7dfbe7cbca8bc59c81d1e6421a527a87796880.
---
src/view-backend-private.cpp | 31 ++++++++++++++++---------------
src/view-backend-private.h | 12 ++++++------
2 files changed, 22 insertions(+), 21 deletions(-)
diff --git a/src/view-backend-private.cpp b/src/view-backend-private.cpp
index e1554bb..6ba3fcb 100644
--- a/src/view-backend-private.cpp
+++ b/src/view-backend-private.cpp
@@ -95,24 +95,33 @@ void ViewBackend::dispatchFrameCallbacks()
if (G_LIKELY(m_bridgeId))
WS::Instance::singleton().dispatchFrameCallbacks(m_bridgeId);
- if (m_client.object)
- wl_client_flush(m_client.object);
+ if (m_client)
+ wl_client_flush(m_client);
wpe_view_backend_dispatch_frame_displayed(m_backend);
}
void ViewBackend::releaseBuffer(struct wl_resource* buffer_resource)
{
wl_buffer_send_release(buffer_resource);
- if (m_client.object)
- wl_client_flush(m_client.object);
+ if (m_client)
+ wl_client_flush(m_client);
}
void ViewBackend::registerSurface(uint32_t bridgeId)
{
m_bridgeId = bridgeId;
- m_client.object = WS::Instance::singleton().registerViewBackend(m_bridgeId, *this);
- m_client.destroyListener.notify = Client::destroyNotify;
- wl_client_add_destroy_listener(m_client.object, &m_client.destroyListener);
+ m_client = WS::Instance::singleton().registerViewBackend(m_bridgeId, *this);
+
+ struct wl_client_destroy_listener *listener = new wl_client_destroy_listener {this, };
+ listener->destroyClientListener.notify = (wl_notify_func_t) [](struct wl_listener* listener, void* data)
+ {
+ struct wl_client_destroy_listener *container;
+ container = wl_container_of(listener, container, destroyClientListener);
+ container->backend->m_client = NULL;
+ delete container; // Release the wl_client_destroy_listener instance since this is not longer needed.
+ };
+ wl_client_add_destroy_listener(m_client,
+ &listener->destroyClientListener);
}
void ViewBackend::unregisterSurface(uint32_t bridgeId)
@@ -137,11 +146,3 @@ void ViewBackend::didReceiveMessage(uint32_t messageId, uint32_t messageBody)
assert(!"WPE fdo received an invalid IPC message");
}
}
-
-void ViewBackend::Client::destroyNotify(struct wl_listener* listener, void*)
-{
- Client* client;
- client = wl_container_of(listener, client, destroyListener);
-
- client->object = nullptr;
-}
diff --git a/src/view-backend-private.h b/src/view-backend-private.h
index 37eab08..81b083c 100644
--- a/src/view-backend-private.h
+++ b/src/view-backend-private.h
@@ -79,12 +79,7 @@ private:
static gboolean s_socketCallback(GSocket*, GIOCondition, gpointer);
uint32_t m_bridgeId { 0 };
- struct Client {
- struct wl_client* object { nullptr };
- struct wl_listener destroyListener;
-
- static void destroyNotify(struct wl_listener*, void*);
- } m_client;
+ struct wl_client* m_client { nullptr };
ClientBundle* m_clientBundle;
struct wpe_view_backend* m_backend;
@@ -93,6 +88,11 @@ private:
int m_clientFd { -1 };
};
+struct wl_client_destroy_listener {
+ ViewBackend* backend;
+ struct wl_listener destroyClientListener;
+};
+
struct wpe_view_backend_private {
wpe_view_backend_private(std::unique_ptr<ClientBundle>&& clientBundle, struct wpe_view_backend* backend)
: clientBundle(std::move(clientBundle))
--
2.31.1

View File

@ -0,0 +1,60 @@
From 862764947c6a62e27371d0b31660ff41cd70b674 Mon Sep 17 00:00:00 2001
From: Adrian Perez de Castro <aperez@igalia.com>
Date: Sat, 10 Apr 2021 18:29:13 +0300
Subject: [PATCH 11/13] Revert "view-backend-exportable-private: Move
ViewBackend::m_destroyClientListener"
This reverts commit d7577891d505a3fb037ec14e54568fe59e310941.
---
src/view-backend-private.cpp | 14 +++++++-------
src/view-backend-private.h | 6 +-----
2 files changed, 8 insertions(+), 12 deletions(-)
diff --git a/src/view-backend-private.cpp b/src/view-backend-private.cpp
index 6ba3fcb..af5472f 100644
--- a/src/view-backend-private.cpp
+++ b/src/view-backend-private.cpp
@@ -112,16 +112,16 @@ void ViewBackend::registerSurface(uint32_t bridgeId)
m_bridgeId = bridgeId;
m_client = WS::Instance::singleton().registerViewBackend(m_bridgeId, *this);
- struct wl_client_destroy_listener *listener = new wl_client_destroy_listener {this, };
- listener->destroyClientListener.notify = (wl_notify_func_t) [](struct wl_listener* listener, void* data)
+ this->m_destroyClientListener.notify = (wl_notify_func_t) [](struct wl_listener* listener, void* data)
{
- struct wl_client_destroy_listener *container;
- container = wl_container_of(listener, container, destroyClientListener);
- container->backend->m_client = NULL;
- delete container; // Release the wl_client_destroy_listener instance since this is not longer needed.
+ ViewBackend *viewBackend = wl_container_of(listener, viewBackend, m_destroyClientListener);
+
+ struct wl_client* client = (struct wl_client*) data;
+ g_debug("ViewBackend <%p>: wl_client <%p> destroy notification for fd %d", viewBackend, data, wl_client_get_fd(client));
+ viewBackend->m_client = NULL;
};
wl_client_add_destroy_listener(m_client,
- &listener->destroyClientListener);
+ &this->m_destroyClientListener);
}
void ViewBackend::unregisterSurface(uint32_t bridgeId)
diff --git a/src/view-backend-private.h b/src/view-backend-private.h
index 81b083c..599382b 100644
--- a/src/view-backend-private.h
+++ b/src/view-backend-private.h
@@ -86,11 +86,7 @@ private:
std::unique_ptr<FdoIPC::Connection> m_socket;
int m_clientFd { -1 };
-};
-
-struct wl_client_destroy_listener {
- ViewBackend* backend;
- struct wl_listener destroyClientListener;
+ struct wl_listener m_destroyClientListener;
};
struct wpe_view_backend_private {
--
2.31.1

View File

@ -0,0 +1,67 @@
From 229b2601804049d94f09006e8c4a542c78158ab9 Mon Sep 17 00:00:00 2001
From: Adrian Perez de Castro <aperez@igalia.com>
Date: Sat, 10 Apr 2021 18:29:24 +0300
Subject: [PATCH 12/13] Revert "view-backend-exportable-private: Add
wl_client_add_destroy_listener in the ViewBackend"
This reverts commit d688cd2558807c1ed15d67e5b0ecfad52a2bf90b.
---
src/view-backend-private.cpp | 17 ++---------------
src/view-backend-private.h | 1 -
2 files changed, 2 insertions(+), 16 deletions(-)
diff --git a/src/view-backend-private.cpp b/src/view-backend-private.cpp
index af5472f..b78831d 100644
--- a/src/view-backend-private.cpp
+++ b/src/view-backend-private.cpp
@@ -95,33 +95,20 @@ void ViewBackend::dispatchFrameCallbacks()
if (G_LIKELY(m_bridgeId))
WS::Instance::singleton().dispatchFrameCallbacks(m_bridgeId);
- if (m_client)
- wl_client_flush(m_client);
+ wl_client_flush(m_client);
wpe_view_backend_dispatch_frame_displayed(m_backend);
}
void ViewBackend::releaseBuffer(struct wl_resource* buffer_resource)
{
wl_buffer_send_release(buffer_resource);
- if (m_client)
- wl_client_flush(m_client);
+ wl_client_flush(m_client);
}
void ViewBackend::registerSurface(uint32_t bridgeId)
{
m_bridgeId = bridgeId;
m_client = WS::Instance::singleton().registerViewBackend(m_bridgeId, *this);
-
- this->m_destroyClientListener.notify = (wl_notify_func_t) [](struct wl_listener* listener, void* data)
- {
- ViewBackend *viewBackend = wl_container_of(listener, viewBackend, m_destroyClientListener);
-
- struct wl_client* client = (struct wl_client*) data;
- g_debug("ViewBackend <%p>: wl_client <%p> destroy notification for fd %d", viewBackend, data, wl_client_get_fd(client));
- viewBackend->m_client = NULL;
- };
- wl_client_add_destroy_listener(m_client,
- &this->m_destroyClientListener);
}
void ViewBackend::unregisterSurface(uint32_t bridgeId)
diff --git a/src/view-backend-private.h b/src/view-backend-private.h
index 599382b..15e98e6 100644
--- a/src/view-backend-private.h
+++ b/src/view-backend-private.h
@@ -86,7 +86,6 @@ private:
std::unique_ptr<FdoIPC::Connection> m_socket;
int m_clientFd { -1 };
- struct wl_listener m_destroyClientListener;
};
struct wpe_view_backend_private {
--
2.31.1

View File

@ -0,0 +1,122 @@
From 328397f4f4d0e6a3608f6fd8c3ec0abdd5763135 Mon Sep 17 00:00:00 2001
From: Adrian Perez de Castro <aperez@igalia.com>
Date: Wed, 14 Apr 2021 15:55:59 +0300
Subject: [PATCH 13/13] ws: Remove wl_client pointer that can end up dangling
Instead of trying to keep track of the destruction of the wl_client
references from ViewBackend::m_client, completely remove the member
variable and instead:
- In ViewBackend::releaseBuffer() use wl_resource_get_client() to obtain
the wl_client from the buffer resource. Given that the buffer resource
has just been used, it is guaranteed that the wl_client it refers to
should be still valid.
- In ViewBackend::dispatchFrameCallbacks() remove the flush call, and
instead do it in WS::Surface::dispatchFrameCallbacks(), and pick the
wl_client from the callback resource objects, if any callback was
dispatched at all. Again, if any callback was dispatched their
associated wl_client should be still valid. Skipping the flush if
no callbacks are dispatched is fine because in that case there would
not be any messages pending be sent over the wire anyway to trigger
dispatching the callbacks in the client side.
---
src/view-backend-private.cpp | 5 ++---
src/view-backend-private.h | 1 -
src/ws.cpp | 3 +--
src/ws.h | 9 ++++++++-
4 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/src/view-backend-private.cpp b/src/view-backend-private.cpp
index b78831d..7e3a738 100644
--- a/src/view-backend-private.cpp
+++ b/src/view-backend-private.cpp
@@ -95,20 +95,19 @@ void ViewBackend::dispatchFrameCallbacks()
if (G_LIKELY(m_bridgeId))
WS::Instance::singleton().dispatchFrameCallbacks(m_bridgeId);
- wl_client_flush(m_client);
wpe_view_backend_dispatch_frame_displayed(m_backend);
}
void ViewBackend::releaseBuffer(struct wl_resource* buffer_resource)
{
wl_buffer_send_release(buffer_resource);
- wl_client_flush(m_client);
+ wl_client_flush(wl_resource_get_client(buffer_resource));
}
void ViewBackend::registerSurface(uint32_t bridgeId)
{
m_bridgeId = bridgeId;
- m_client = WS::Instance::singleton().registerViewBackend(m_bridgeId, *this);
+ WS::Instance::singleton().registerViewBackend(m_bridgeId, *this);
}
void ViewBackend::unregisterSurface(uint32_t bridgeId)
diff --git a/src/view-backend-private.h b/src/view-backend-private.h
index 15e98e6..363b787 100644
--- a/src/view-backend-private.h
+++ b/src/view-backend-private.h
@@ -79,7 +79,6 @@ private:
static gboolean s_socketCallback(GSocket*, GIOCondition, gpointer);
uint32_t m_bridgeId { 0 };
- struct wl_client* m_client { nullptr };
ClientBundle* m_clientBundle;
struct wpe_view_backend* m_backend;
diff --git a/src/ws.cpp b/src/ws.cpp
index 87faaf3..622bbf3 100644
--- a/src/ws.cpp
+++ b/src/ws.cpp
@@ -519,14 +519,13 @@ void Instance::releaseAudioPacketExport(struct wpe_audio_packet_export* packet_e
wpe_audio_packet_export_send_release(packet_export->exportResource);
}
-struct wl_client* Instance::registerViewBackend(uint32_t bridgeId, APIClient& apiClient)
+void Instance::registerViewBackend(uint32_t bridgeId, APIClient& apiClient)
{
auto it = m_viewBackendMap.find(bridgeId);
if (it == m_viewBackendMap.end())
g_error("Instance::registerViewBackend(): " "Cannot find surface with bridgeId %" PRIu32 " in view backend map.", bridgeId);
it->second->apiClient = &apiClient;
- return wl_resource_get_client(it->second->resource);
}
void Instance::unregisterViewBackend(uint32_t bridgeId)
diff --git a/src/ws.h b/src/ws.h
index 30baf8e..1bf528e 100644
--- a/src/ws.h
+++ b/src/ws.h
@@ -88,10 +88,17 @@ struct Surface {
{
struct wl_resource* resource;
struct wl_resource* tmp;
+ struct wl_client* client { nullptr };
+
wl_resource_for_each_safe(resource, tmp, &m_currentFrameCallbacks) {
+ g_assert(!client || client == wl_resource_get_client(resource));
+ client = wl_resource_get_client(resource);
wl_callback_send_done(resource, 0);
wl_resource_destroy(resource);
}
+
+ if (client)
+ wl_client_flush(client);
}
private:
@@ -129,7 +136,7 @@ public:
int createClient();
void registerSurface(uint32_t, Surface*);
- struct wl_client* registerViewBackend(uint32_t, APIClient&);
+ void registerViewBackend(uint32_t, APIClient&);
void unregisterViewBackend(uint32_t);
void dispatchFrameCallbacks(uint32_t);
--
2.31.1

View File

@ -2,13 +2,27 @@
Name: wpebackend-fdo
Version: 1.9.90
Release: 1%{?dist}
Release: 2%{?dist}
Summary: A WPE backend designed for Linux desktop systems
License: BSD
URL: https://github.com/Igalia/%{name}
Source0: https://github.com/Igalia/%{name}/archive/%{version}/%{name}-%{version}.tar.xz
# https://github.com/Igalia/WPEBackend-fdo/issues/145
Patch0: 0001-Add-some-checks-to-ensure-we-properly-bind-server-gl.patch
Patch1: 0002-ws-Remove-unneeded-Surface-id-member.patch
Patch2: 0003-ws-Rename-surfaceId-to-bridgeId-where-appropriate.patch
Patch3: 0004-ws-Accumulate-surface-frame-callbacks-until-commit.patch
Patch4: 0006-meson-Make-scripts-version.py-work-with-older-Python.patch
Patch5: 0007-Revert-view-backend-Properly-unregister-surfaces.patch
Patch6: 0008-Revert-view-backend-private-Move-wl_client_destroy-t.patch
Patch7: 0009-Revert-ws-Call-wl_client_destroy-for-the-created-wl_.patch
Patch8: 0010-Revert-Cleanups.patch
Patch9: 0011-Revert-view-backend-exportable-private-Move-ViewBack.patch
Patch10: 0012-Revert-view-backend-exportable-private-Add-wl_client.patch
Patch11: 0013-ws-Remove-wl_client-pointer-that-can-end-up-dangling.patch
BuildRequires: gcc-c++
BuildRequires: meson
BuildRequires: pkgconfig(egl)
@ -53,6 +67,9 @@ files for developing applications that use %{name}.
%{_libdir}/pkgconfig/wpebackend-fdo-1.0.pc
%changelog
* Sat Apr 17 2021 Michael Catanzaro <mcatanzaro@redhat.com> - 1.9.90-2
- Stop crashing after process swap
* Thu Apr 01 2021 Michael Catanzaro <mcatanzaro@redhat.com> - 1.9.90-1
- Update to 1.9.90