Fix crashes and memory leaks during display deinitialization

* .dir-locals.el (c-mode): Add more noise macro names.
* src/frame.c (delete_frame): Do not delete terminal if force is
Qnoelisp.

* src/xterm.c (x_wm_supports): Fix coding style.
(x_delete_display): Delete the supported atoms list.
(x_delete_terminal): Delete all terminals.  Free the scratch
cursor GC.
This commit is contained in:
Po Lu 2022-12-01 14:21:14 +08:00
parent 785fa80159
commit 4161023a63
3 changed files with 40 additions and 7 deletions

View file

@ -11,7 +11,8 @@
(vc-prepare-patches-separately . nil)))
(c-mode . ((c-file-style . "GNU")
(c-noise-macro-names . ("INLINE" "NO_INLINE" "ATTRIBUTE_NO_SANITIZE_UNDEFINED"
"UNINIT" "CALLBACK" "ALIGN_STACK"))
"UNINIT" "CALLBACK" "ALIGN_STACK" "ATTRIBUTE_MALLOC"
"ATTRIBUTE_DEALLOC_FREE"))
(electric-quote-comment . nil)
(electric-quote-string . nil)
(indent-tabs-mode . t)

View file

@ -2214,17 +2214,24 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
/* Since a similar behavior was observed on the Lucid and Motif
builds (see Bug#5802, Bug#21509, Bug#23499, Bug#27816), we now
don't delete the terminal for these builds either. */
if (terminal->reference_count == 0 &&
(terminal->type == output_x_window || terminal->type == output_pgtk))
if (terminal->reference_count == 0
&& (terminal->type == output_x_window
|| terminal->type == output_pgtk))
terminal->reference_count = 1;
#endif /* USE_X_TOOLKIT || USE_GTK */
if (terminal->reference_count == 0)
{
Lisp_Object tmp;
XSETTERMINAL (tmp, terminal);
kb = NULL;
Fdelete_terminal (tmp, NILP (force) ? Qt : force);
/* If force is noelisp, the terminal is going away inside
x_delete_terminal, and a recursive call to Fdelete_terminal
is unsafe! */
if (!EQ (force, Qnoelisp))
Fdelete_terminal (tmp, NILP (force) ? Qt : force);
}
else
kb = terminal->kboard;

View file

@ -26768,13 +26768,14 @@ x_wm_supports_1 (struct x_display_info *dpyinfo, Atom want_atom)
if (rc != Success || actual_type != XA_ATOM || x_had_errors_p (dpy))
{
if (tmp_data) XFree (tmp_data);
if (tmp_data)
XFree (tmp_data);
x_uncatch_errors ();
unblock_input ();
return false;
}
dpyinfo->net_supported_atoms = (Atom *)tmp_data;
dpyinfo->net_supported_atoms = (Atom *) tmp_data;
dpyinfo->nr_net_supported_atoms = actual_size;
dpyinfo->net_supported_window = wmcheck_window;
}
@ -30630,6 +30631,9 @@ x_delete_display (struct x_display_info *dpyinfo)
}
}
if (dpyinfo->net_supported_atoms)
XFree (dpyinfo->net_supported_atoms);
xfree (dpyinfo->color_names);
xfree (dpyinfo->color_names_length);
xfree (dpyinfo->x_id_name);
@ -30741,7 +30745,11 @@ static struct redisplay_interface x_redisplay_interface =
void
x_delete_terminal (struct terminal *terminal)
{
struct x_display_info *dpyinfo = terminal->display_info.x;
struct x_display_info *dpyinfo;
struct frame *f;
Lisp_Object tail, frame;
dpyinfo = terminal->display_info.x;
/* Protect against recursive calls. delete_frame in
delete_terminal calls us back when it deletes our last frame. */
@ -30749,6 +30757,19 @@ x_delete_terminal (struct terminal *terminal)
return;
block_input ();
/* Delete all remaining frames on the display that is going away.
Otherwise, font backends assume the display is still up, and
xftfont_end_for_frame crashes. */
FOR_EACH_FRAME (tail, frame)
{
f = XFRAME (frame);
if (FRAME_LIVE_P (f) && f->terminal == terminal)
/* Pass Qnoelisp rather than Qt. */
delete_frame (frame, Qnoelisp);
}
#ifdef HAVE_X_I18N
/* We must close our connection to the XIM server before closing the
X display. */
@ -30762,6 +30783,10 @@ x_delete_terminal (struct terminal *terminal)
image_destroy_all_bitmaps (dpyinfo);
XSetCloseDownMode (dpyinfo->display, DestroyAll);
/* Delete the scratch cursor GC, should it exist. */
if (dpyinfo->scratch_cursor_gc)
XFreeGC (dpyinfo->display, dpyinfo->scratch_cursor_gc);
/* Get rid of any drag-and-drop operation that might be in
progress as well. */
if ((x_dnd_in_progress || x_dnd_waiting_for_finish)