bug-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#43389: 28.0.50; Emacs memory leaks using hard disk all time


From: Trevor Bentley
Subject: bug#43389: 28.0.50; Emacs memory leaks using hard disk all time
Date: Wed, 20 Jan 2021 13:02:23 +0100

I tried setting a breakpoint in longjmp, but it's called 3 times for every keypress! That's inconvenient. Running one single instance now with a conditional breakpoint on longjmp: it will break if longjmp is called while it's in unblock_input().

I disappeared for ages because... the problem disappeared. I went a month without reproducing it, despite putting a hold on upgrading both system and emacs packages while debugging. Very odd.

But today it appeared again. And, for the first time, in a gdb session with breakpoints to confirm my theory. I believe I've found the underlying issue.

If you have a look at this long backtrace, you can see that we are inside a garbage_collect call (frame #38). An X11 focus event comes in, triggering a bunch of GTK/GDK/X calls. Mysteriously, this leads to a maybe_quit() call which in turn calls longjmp(). longjmp jumps right out of the garbage collect, leaving it unfinished.

Internally in garbage_collect, consing_until_gc was set to the HI_THRESHOLD upper-bound. It is left that way when longjmp leaps out of it, and no automatic garbage collect is ever performed again. This is the start of the ballooning memory.

This also explains why my minimized emacs session never hits it and my work sessions hit it very often, and less often on weekends. It's triggered by focus events. I flitter around between windows constantly while working.

I don't know emacs internals, so you'll have to figure out if this is X dependent (probably) and/or GTK dependent. It should be possible to come up with an easier way to reproduce it now.

Backtrace:
-----------
(gdb) bt #0 0x00007ffff5571230 in siglongjmp () at /usr/lib/libc.so.6 #1 0x00005555557bd38d in unwind_to_catch (catch=0x555555dfc320, type=NONLOCAL_EXIT_THROW, value=0x30) at eval.c:1181 #2 0x00005555557bd427 in Fthrow (tag=0xe75830, value=0x30) at eval.c:1198 #3 0x00005555557bdea7 in process_quit_flag () at eval.c:1526 #4 0x00005555557bdeef in maybe_quit () at eval.c:1547 #5 0x00005555557cbbb1 in Fassq (key=0xd0b0, alist=0x55555901c573) at fns.c:1609 #6 0x0000555555632b63 in window_parameter (w=0x555555f2d088, parameter=0xd0b0) at window.c:2262 #7 0x000055555563a075 in window_wants_tab_line (w=0x555555f2d088) at window.c:5410 #8 0x00005555555c22b1 in get_phys_cursor_geometry (w=0x555555f2d088, row=0x55555d9f3ef0, glyph=0x55555fd20e00, xp=0x7fffffff9c48, yp=0x7fffffff9c4c, heightp=0x7fffffff9c50) at xdisp.c:2650 #9 0x00005555556c1b12 in x_draw_hollow_cursor (w=0x555555f2d088, row=0x55555d9f3ef0) at xterm.c:9495 #10 0x00005555556c24f9 in x_draw_window_cursor (w=0x555555f2d088, glyph_row=0x55555d9f3ef0, x=32, y=678, cursor_type=HOLLOW_BOX_CURSOR, cursor_width=1, on_p=true, active_p=false) at xterm.c:9682 #11 0x000055555561a922 in display_and_set_cursor (w=0x555555f2d088, on=true, hpos=2, vpos=18, x=32, y=678) at xdisp.c:31738 #12 0x000055555561aa5b in update_window_cursor (w=0x555555f2d088, on=true) at xdisp.c:31773 #13 0x000055555561aabf in update_cursor_in_window_tree (w=0x555555f2d088, on_p=true) at xdisp.c:31791 #14 0x000055555561aaab in update_cursor_in_window_tree (w=0x55555907a490, on_p=true) at xdisp.c:31789 #15 0x000055555561aaab in update_cursor_in_window_tree (w=0x55555a514b68, on_p=true) at xdisp.c:31789 #16 0x000055555561ab37 in gui_update_cursor (f=0x555556625468, on_p=true) at xdisp.c:31805 #17 0x00005555556b9829 in x_frame_unhighlight (f=0x555556625468) at xterm.c:4490 #18 0x00005555556ba22d in x_frame_rehighlight (dpyinfo=0x55555626d6c0) at xterm.c:4852 #19 0x00005555556b98fc in x_new_focus_frame (dpyinfo=0x55555626d6c0, frame=0x0) at xterm.c:4520 #20 0x00005555556b9a3d in x_focus_changed (type=10, state=2, dpyinfo=0x55555626d6c0, frame=0x555556625468, bufp=0x7fffffffa0d0) at xterm.c:4554 #21 0x00005555556ba0a6 in x_detect_focus_change (dpyinfo=0x55555626d6c0, frame=0x555556625468, event=0x7fffffffa840, bufp=0x7fffffffa0d0) at xterm.c:4787 #22 0x00005555556c0235 in handle_one_xevent (dpyinfo=0x55555626d6c0, event=0x7fffffffa840, finish=0x555555c901d4 <current_finish>, hold_quit=0x7fffffffab50) at xterm.c:8810 #23 0x00005555556bde28 in event_handler_gdk (gxev=0x7fffffffa840, ev=0x55555cccf0c0, data=0x0) at xterm.c:7768 #24 0x00007ffff75f780f in () at /usr/lib/libgdk-3.so.0 #25 0x00007ffff75fb3cb in () at /usr/lib/libgdk-3.so.0 #26 0x00007ffff759f15b in gdk_display_get_event () at /usr/lib/libgdk-3.so.0 #27 0x00007ffff75fb104 in () at /usr/lib/libgdk-3.so.0 #28 0x00007ffff6fcb8f4 in g_main_context_dispatch () at /usr/lib/libglib-2.0.so.0 #29 0x00007ffff701f821 in () at /usr/lib/libglib-2.0.so.0 #30 0x00007ffff6fca121 in g_main_context_iteration () at /usr/lib/libglib-2.0.so.0 #31 0x00007ffff784e2c7 in gtk_main_iteration () at /usr/lib/libgtk-3.so.0 #32 0x00005555556c1821 in XTread_socket (terminal=0x5555560b7460, hold_quit=0x7fffffffab50) at xterm.c:9395 #33 0x000055555570f3a2 in gobble_input () at keyboard.c:6890 #34 0x000055555570f894 in handle_async_input () at keyboard.c:7121 #35 0x000055555570f8dd in process_pending_signals () at keyboard.c:7139 #36 0x000055555570f9cf in unblock_input_to (level=0) at keyboard.c:7162 #37 0x000055555570fa4c in unblock_input () at keyboard.c:7187 #38 0x000055555578f49a in garbage_collect () at alloc.c:6121 #39 0x000055555578efe7 in maybe_garbage_collect () at alloc.c:5964 #40 0x00005555557bb292 in maybe_gc () at lisp.h:5041 #41 0x00005555557c12d6 in Ffuncall (nargs=2, args=0x7fffffffad68) at eval.c:2793 #42 0x000055555580f7d6 in exec_byte_code
...  --------------

For breakpoints, I am doing the following:

1) make a global static variable in alloc.c:
static int enable_gc_trace = 0;

2) in garbage_collect(), 'enable_gc_trace++' when it starts and 'enable_gc_trace--' when it ends. I just wrapped the call to unblock_input(), but you could widen that window.

3) run in gdb with conditional breakpoints on GC and longjmp functions:
b siglongjmp if enable_gc_trace > 0
b internal_catch if enable_gc_trace > 0
b internal_catch_all if enable_gc_trace > 0
b maybe_garbage_collect if enable_gc_trace > 0

-Trevor





reply via email to

[Prev in Thread] Current Thread [Next in Thread]