This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch wl/real-browser
in repository enlightenment.
View the commit online.
commit 1a081cccd8b0bf7695896cf2ba3e984f34fcfa45
Author: Cedric BAIL <[email protected]>
AuthorDate: Sun Aug 16 22:47:36 2026 -0600
e_pixmap - do not hand back a buffer the renderer may still be reading
Dragging a window's corner to resize it killed the compositor, every time:
#0 _evas_common_scale_rgba_sample_scale_nomask
#1 evas_common_scale_rgba_sample_draw
#2 _draw_thread_image_draw
#3 evas_thread_worker_func
SEGV_MAPERR in evas's async render thread, reading image data that is no
longer mapped.
e_pixmap already knows about this. _e_pixmap_wayland_buffer_release holds a
release back while e_comp->rendering, precisely so a client is not told it may
reuse or destroy a buffer the compositor has not finished with.
e_pixmap_resource_set did not go through it - it called
_e_pixmap_wl_resource_release directly, with the busy_list bookkeeping copied
inline - so the one path that always fires on a client committing a *new*
buffer was the one path with no deferral.
That is the worst place to miss it. Committing a new buffer is exactly when the
old one gets handed back, and during a resize new buffers arrive faster than
frames go out. The client did what it is entitled to do: it got the release, it
destroyed the buffer, libwayland dropped the shm pool's mapping, and the worker
was still reading from it. Every toolkit destroys released buffers - the test
client here does, and so does every browser. It just takes a resize to make the
overlap likely enough to hit every time.
So call the wrapper. The busy_list handling it does inline is the same handling
the wrapper already has, so nothing else changes.
Found by test_client_move.c, which drives an interactive corner drag through
E's own resize grab; it crashed the compositor on every run before this and
passes five for five after. wl-globals, all eleven protocol tests and
e_wlcs_driver pass.
One thing deliberately not changed: e_comp->rendering is cleared from
RENDER_FLUSH_POST, which is when drawing is handed to evas rather than when the
worker has finished with it, so in principle the deferral window closes early.
Moving it to RENDER_POST also fixes this crash - but so does the one-line
change above on its own, five runs out of five, and a stuck rendering flag
would starve every client of buffer releases. Not worth trading a crash I can
reproduce for a hang I cannot.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
---
src/bin/e_pixmap.c | 29 +++++++++++++++++------------
1 file changed, 17 insertions(+), 12 deletions(-)
diff --git a/src/bin/e_pixmap.c b/src/bin/e_pixmap.c
index 0c14e569c..16e1461fb 100644
--- a/src/bin/e_pixmap.c
+++ b/src/bin/e_pixmap.c
@@ -763,18 +763,23 @@ e_pixmap_resource_set(E_Pixmap *cp, void *resource)
#ifdef HAVE_WAYLAND
if (cp->buffer == resource) return;
- if (cp->buffer)
- {
- if (resource)
- {
- if (cp->buffer->busy == 1)
- {
- // about to go to busy 0, so remove from list
- cp->busy_list = eina_list_remove(cp->busy_list, cp->buffer);
- }
- _e_pixmap_wl_resource_release(cp->buffer);
- }
- }
+ /* Through _e_pixmap_wayland_buffer_release, not straight to
+ * _e_pixmap_wl_resource_release. The difference is the only thing standing
+ * between a client and a compositor crash: the wrapper holds a release back
+ * while a render is in flight, and this is exactly when that matters - the
+ * client has just committed a new buffer, so the old one is about to be
+ * handed back while evas may still be reading it from a worker thread.
+ *
+ * Releasing it immediately told the client it could destroy the buffer, and
+ * destroying it dropped the shm mapping the worker was reading, inside
+ * evas_common_scale_rgba_sample_draw. It takes a resize to make it likely
+ * enough to see, because that is when new buffers arrive faster than frames
+ * go out - but every toolkit destroys released buffers, so nothing about it
+ * is exotic.
+ *
+ * The busy_list bookkeeping this used to do inline lives in the wrapper. */
+ if (cp->buffer && resource)
+ _e_pixmap_wayland_buffer_release(cp, cp->buffer);
if (cp->buffer_destroy_listener.notify)
{
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.