|
| 1 | +From: Mirko Vogt <foss@mirko.in> |
| 2 | +Subject: [PATCH] ws: do not export a stale buffer on a commit without attach |
| 3 | + |
| 4 | +Surface::shmBuffer (and, in the EGL implementation, also dmabufBuffer) |
| 5 | +is set at wl_surface.attach and was never cleared: a commit without a |
| 6 | +fresh attach - e.g. one issued only for frame-callback pacing - |
| 7 | +re-exported the previous buffer pointer. Once the client had destroyed |
| 8 | +that buffer after its release, the embedder received a dangling |
| 9 | +wl_shm_buffer whose metadata reads as garbage (observed as negative |
| 10 | +width/stride crashing cog's drm renderer copy loop). |
| 11 | + |
| 12 | +Consume the attached buffer state at commit and export nothing when no |
| 13 | +buffer was attached. Apply to both ImplSHM and ImplEGL - the code is |
| 14 | +duplicated between ws-shm.cpp and ws-egl.cpp. |
| 15 | + |
| 16 | +Signed-off-by: Mirko Vogt <foss@mirko.in> |
| 17 | +--- |
| 18 | +--- a/src/ws-shm.cpp |
| 19 | ++++ b/src/ws-shm.cpp |
| 20 | +@@ -47,8 +47,19 @@ |
| 21 | + struct wl_resource* bufferResource = surface.bufferResource; |
| 22 | + surface.bufferResource = nullptr; |
| 23 | + |
| 24 | +- if (surface.shmBuffer) |
| 25 | +- surface.apiClient->exportShmBuffer(bufferResource, surface.shmBuffer); |
| 26 | ++ // Consume the buffer state: it belongs to the buffer attached for THIS |
| 27 | ++ // commit. Leaving it set would re-export a stale - and, once the client |
| 28 | ++ // destroyed the released buffer, dangling - pointer on a commit that |
| 29 | ++ // did not attach a new buffer (e.g. a commit issued only for |
| 30 | ++ // frame-callback pacing), handing the embedder garbage metadata. |
| 31 | ++ struct wl_shm_buffer* shmBuffer = surface.shmBuffer; |
| 32 | ++ surface.shmBuffer = nullptr; |
| 33 | ++ |
| 34 | ++ if (!bufferResource) |
| 35 | ++ return; |
| 36 | ++ |
| 37 | ++ if (shmBuffer) |
| 38 | ++ surface.apiClient->exportShmBuffer(bufferResource, shmBuffer); |
| 39 | + else |
| 40 | + surface.apiClient->exportBufferResource(bufferResource); |
| 41 | + } |
| 42 | +--- a/src/ws-egl.cpp |
| 43 | ++++ b/src/ws-egl.cpp |
| 44 | +@@ -102,10 +102,20 @@ |
| 45 | + struct wl_resource* bufferResource = surface.bufferResource; |
| 46 | + surface.bufferResource = nullptr; |
| 47 | + |
| 48 | +- if (surface.dmabufBuffer) |
| 49 | +- surface.apiClient->exportLinuxDmabuf(surface.dmabufBuffer); |
| 50 | +- else if (surface.shmBuffer) |
| 51 | +- surface.apiClient->exportShmBuffer(bufferResource, surface.shmBuffer); |
| 52 | ++ // Consume the buffer state (see ws-shm.cpp): stale dmabuf/shm pointers |
| 53 | ++ // must never be re-exported on a commit without a fresh attach. |
| 54 | ++ const struct linux_dmabuf_buffer* dmabufBuffer = surface.dmabufBuffer; |
| 55 | ++ surface.dmabufBuffer = nullptr; |
| 56 | ++ struct wl_shm_buffer* shmBuffer = surface.shmBuffer; |
| 57 | ++ surface.shmBuffer = nullptr; |
| 58 | ++ |
| 59 | ++ if (!bufferResource) |
| 60 | ++ return; |
| 61 | ++ |
| 62 | ++ if (dmabufBuffer) |
| 63 | ++ surface.apiClient->exportLinuxDmabuf(dmabufBuffer); |
| 64 | ++ else if (shmBuffer) |
| 65 | ++ surface.apiClient->exportShmBuffer(bufferResource, shmBuffer); |
| 66 | + else |
| 67 | + surface.apiClient->exportBufferResource(bufferResource); |
| 68 | + } |
0 commit comments