]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix crash upon call to Fset_fontset_font after X server disconnect
authorPo Lu <luangruo@yahoo.com>
Sat, 13 Apr 2024 11:43:40 +0000 (19:43 +0800)
committerEshel Yaron <me@eshelyaron.com>
Sun, 14 Apr 2024 17:10:30 +0000 (19:10 +0200)
* src/image.c (free_image):

* src/xfaces.c (free_realized_face): Handle scenarios where
free_frame_faces is called with the display connection cut.

* src/xterm.c (x_free_frame_resources): Call free_frame_faces
unconditionally, lest fontsets for this dead frame contaminate
Vfontset_list and produce crashes afterwards.  (bug#66151)

(cherry picked from commit 9fc698479feef6fa660ff13e21619ea50bd404df)

src/image.c
src/xfaces.c
src/xterm.c

index 216bdc1ee66b647a8ab014146829b83cbf995423..3968145728fd98966e825ee667182754c645cf20 100644 (file)
@@ -1699,14 +1699,26 @@ free_image (struct frame *f, struct image *img)
       c->images[img->id] = NULL;
 
 #if !defined USE_CAIRO && defined HAVE_XRENDER
-      if (img->picture)
-        XRenderFreePicture (FRAME_X_DISPLAY (f), img->picture);
-      if (img->mask_picture)
-        XRenderFreePicture (FRAME_X_DISPLAY (f), img->mask_picture);
-#endif
+      /* FRAME_X_DISPLAY (f) could be NULL if this is being called from
+        the display IO error handler.*/
+
+      if (FRAME_X_DISPLAY (f))
+       {
+         if (img->picture)
+           XRenderFreePicture (FRAME_X_DISPLAY (f),
+                               img->picture);
+         if (img->mask_picture)
+           XRenderFreePicture (FRAME_X_DISPLAY (f),
+                               img->mask_picture);
+       }
+#endif /* !USE_CAIRO && HAVE_XRENDER */
+
+#ifdef HAVE_X_WINDOWS
+      if (FRAME_X_DISPLAY (f))
+#endif /* HAVE_X_WINDOWS */
+       /* Free resources, then free IMG.  */
+       img->type->free_img (f, img);
 
-      /* Free resources, then free IMG.  */
-      img->type->free_img (f, img);
       xfree (img->face_font_family);
       xfree (img);
     }
index a558e7328c0a6169a0daed349ffb601ec6ca928d..d4583e1a78f8aa4b4e129fe767e7aa962ea69446 100644 (file)
@@ -4569,6 +4569,15 @@ free_realized_face (struct frame *f, struct face *face)
          /* Free fontset of FACE if it is ASCII face.  */
          if (face->fontset >= 0 && face == face->ascii_face)
            free_face_fontset (f, face);
+
+#ifdef HAVE_X_WINDOWS
+         /* This function might be called with the frame's display
+            connection deleted, in which event the callbacks below
+            should not be executed, as they generate X requests.  */
+         if (FRAME_X_DISPLAY (f))
+           return;
+#endif /* HAVE_X_WINDOWS */
+
          if (face->gc)
            {
              block_input ();
index 5e5eb6269e45dc95ce2128c7424218fa3a06a8d9..e08ffd15b18d6bf6adc7ffb9e4ce582d80c6d7d7 100644 (file)
@@ -29428,6 +29428,17 @@ x_free_frame_resources (struct frame *f)
   xi_unlink_touch_points (f);
 #endif
 
+  /* We must free faces before destroying windows because some
+     font-driver (e.g. xft) access a window while finishing a face.
+
+     This function must be called to remove this frame's fontsets from
+     Vfontset_list, and is itself responsible for not issuing X requests
+     if the connection has already been terminated.  Otherwise, a future
+     call to a function that iterates over all existing fontsets might
+     crash, as they are not prepared to receive dead frames.
+     (bug#66151) */
+  free_frame_faces (f);
+
   /* If a display connection is dead, don't try sending more
      commands to the X server.  */
   if (dpyinfo->display)
@@ -29437,10 +29448,6 @@ x_free_frame_resources (struct frame *f)
       if (f->pointer_invisible)
        XTtoggle_invisible_pointer (f, 0);
 
-      /* We must free faces before destroying windows because some
-        font-driver (e.g. xft) access a window while finishing a
-        face.  */
-      free_frame_faces (f);
       tear_down_x_back_buffer (f);
 
       if (f->output_data.x->icon_desc)