emacs-diffs
[Top][All Lists]
Advanced

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

emacs-29 4161023a63: Fix crashes and memory leaks during display deiniti


From: Po Lu
Subject: emacs-29 4161023a63: Fix crashes and memory leaks during display deinitialization
Date: Thu, 1 Dec 2022 01:23:25 -0500 (EST)

branch: emacs-29
commit 4161023a63d68534d3e70931645ac82a88330334
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    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.
---
 .dir-locals.el |  3 ++-
 src/frame.c    | 13 ++++++++++---
 src/xterm.c    | 31 ++++++++++++++++++++++++++++---
 3 files changed, 40 insertions(+), 7 deletions(-)

diff --git a/.dir-locals.el b/.dir-locals.el
index f0ab46236f..fc89dff87f 100644
--- a/.dir-locals.el
+++ b/.dir-locals.el
@@ -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)
diff --git a/src/frame.c b/src/frame.c
index b57b296be5..05106a6c75 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -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;
diff --git a/src/xterm.c b/src/xterm.c
index 7eaf59d54b..44fad6e8d5 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -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)



reply via email to

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