possible leak of virtual memory on gtk-3 wayland
I'm testing emacs-29 built with Pgtk (with gtk+-3.24.41), and I suspect there may be a memory leak in virtual memory.
Steps to reproduce
- Start Emacs with "-Q --bg-daemon=mytest".
- Connect to the server with
emacsclient -c -s mytest
. This will create a new frame. - Kill the newly created frame with
\C-x\C-c
. - Repeat steps 2 & 3, and observe
/proc/pid_of_emacs/maps
.
It seems like there could be a memory leak issue causing the increasing number of "/memfd:gdk-wayland" entries and ultimately leading to the crash without a core dump.
Some of my statistics are as follows:
# yyc <at> tbook in /proc/400602 [18:40:36]
$ cat maps | grep memfd | awk '{print $1}' | awk -F "-" '{sum=strtonum("0x"$2)-strtonum("0x"$1); print sum}' | awk '{sum+=$1} END {print sum}'
42688512
# yyc <at> tbook in /proc/400602 [18:40:57]
$ cat maps | grep memfd | awk '{print $1}' | awk -F "-" '{sum=strtonum("0x"$2)-strtonum("0x"$1); print sum}' | awk '{sum+=$1} END {print sum}'
51888128
# yyc <at> tbook in /proc/400602 [18:41:26]
$ cat /proc/400602/maps| grep /memfd: | wc -l
7
# yyc <at> tbook in /proc/400602 [18:41:41]
$ cat /proc/400602/maps| grep /memfd: | wc -l
9
# yyc <at> tbook in /proc/400602 [18:41:46]
$ cat /proc/400602/maps| grep /memfd: | wc -l
10
# yyc <at> tbook in /proc/400602 [18:41:51]
$ cat /proc/400602/maps| grep /memfd: | wc -l
10
# yyc <at> tbook in /proc/400602 [18:41:56]
$ cat /proc/400602/maps| grep /memfd: | wc -l
12
# yyc <at> tbook in /proc/400602 [18:42:01]
$ cat /proc/400602/maps| grep /memfd: | wc -l
12
# yyc <at> tbook in /proc/400602 [18:42:03]
$ cat /proc/400602/maps| grep /memfd:
7f0ca170a000-7f0ca1fd0000 rw-s 00000000 00:01 169719 /memfd:gdk-wayland (deleted)
7f0ca1fd0000-7f0ca2896000 rw-s 00000000 00:01 169718 /memfd:gdk-wayland (deleted)
7f0ca2896000-7f0ca315c000 rw-s 00000000 00:01 175557 /memfd:gdk-wayland (deleted)
7f0ca315c000-7f0ca3a22000 rw-s 00000000 00:01 169709 /memfd:gdk-wayland (deleted)
7f0ca3a22000-7f0ca42e8000 rw-s 00000000 00:01 169708 /memfd:gdk-wayland (deleted)
7f0ca42e8000-7f0ca4bae000 rw-s 00000000 00:01 177320 /memfd:gdk-wayland (deleted)
7f0ca4bae000-7f0ca5474000 rw-s 00000000 00:01 176334 /memfd:gdk-wayland (deleted)
7f0ca5474000-7f0ca5d3a000 rw-s 00000000 00:01 175525 /memfd:gdk-wayland (deleted)
7f0ca5d3a000-7f0ca6600000 rw-s 00000000 00:01 175517 /memfd:gdk-wayland (deleted)
7f0ca773a000-7f0ca8000000 rw-s 00000000 00:01 175524 /memfd:gdk-wayland (deleted)
7f0cc4381000-7f0cc47ff000 rw-s 00000000 00:01 175518 /memfd:wayland-cursor (deleted)
7f0cc66da000-7f0cc67fa000 rw-s 00000000 00:01 175514 /memfd:wayland-cursor (deleted)
Current behavior
Virtual memory is not released.
Expected outcome
No memory leak, allocated shared memory should be released effectively.
Version information
gentoo 23, gtk+-3.24.41 from binpkg (binary package from gentoo)
Additional information
Add following change seems work in this scenario:
diff -urNa gtk+-3.24.41.orig/gdk/wayland/gdkwindow-wayland.c gtk+-3.24.41/gdk/wayland/gdkwindow-wayland.c
--- gtk+-3.24.41.orig/gdk/wayland/gdkwindow-wayland.c 2024-01-24 09:14:34.000000000 +0800
+++ gtk+-3.24.41/gdk/wayland/gdkwindow-wayland.c 2024-04-29 16:41:00.691373426 +0800
@@ -952,6 +952,11 @@
/* Release came in, we haven't done any interim updates, so we can just use
* the old committed buffer again.
*/
+
+ if (impl->staging_cairo_surface) {
+ g_clear_pointer (&impl->staging_cairo_surface, cairo_surface_destroy);
+ }
+
impl->staging_cairo_surface = g_steal_pointer (&impl->committed_cairo_surface);
}
Actually, I do not understand the logic of the function buffer_release_callback()
, but when
debugging this issue with gdb, I noticed that the impl->staging_cairo_surface
which was created via
_gdk_wayland_display_create_shm_surface
was replaced by `impl->committed_cairo_surface' without being released first.