diff options
| author | Po Lu | 2024-04-13 19:43:40 +0800 |
|---|---|---|
| committer | Po Lu | 2024-04-13 19:44:34 +0800 |
| commit | 9fc698479feef6fa660ff13e21619ea50bd404df (patch) | |
| tree | 89af5b1e136fd6273db592a61e2255bb3a4ea717 | |
| parent | adbcf268bc81c439f90b1016700d8a0a234e12b7 (diff) | |
| download | emacs-9fc698479feef6fa660ff13e21619ea50bd404df.tar.gz emacs-9fc698479feef6fa660ff13e21619ea50bd404df.zip | |
Fix crash upon call to Fset_fontset_font after X server disconnect
* 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)
| -rw-r--r-- | src/image.c | 26 | ||||
| -rw-r--r-- | src/xfaces.c | 9 | ||||
| -rw-r--r-- | src/xterm.c | 15 |
3 files changed, 39 insertions, 11 deletions
diff --git a/src/image.c b/src/image.c index 216bdc1ee66..3968145728f 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -1699,14 +1699,26 @@ free_image (struct frame *f, struct image *img) | |||
| 1699 | c->images[img->id] = NULL; | 1699 | c->images[img->id] = NULL; |
| 1700 | 1700 | ||
| 1701 | #if !defined USE_CAIRO && defined HAVE_XRENDER | 1701 | #if !defined USE_CAIRO && defined HAVE_XRENDER |
| 1702 | if (img->picture) | 1702 | /* FRAME_X_DISPLAY (f) could be NULL if this is being called from |
| 1703 | XRenderFreePicture (FRAME_X_DISPLAY (f), img->picture); | 1703 | the display IO error handler.*/ |
| 1704 | if (img->mask_picture) | 1704 | |
| 1705 | XRenderFreePicture (FRAME_X_DISPLAY (f), img->mask_picture); | 1705 | if (FRAME_X_DISPLAY (f)) |
| 1706 | #endif | 1706 | { |
| 1707 | if (img->picture) | ||
| 1708 | XRenderFreePicture (FRAME_X_DISPLAY (f), | ||
| 1709 | img->picture); | ||
| 1710 | if (img->mask_picture) | ||
| 1711 | XRenderFreePicture (FRAME_X_DISPLAY (f), | ||
| 1712 | img->mask_picture); | ||
| 1713 | } | ||
| 1714 | #endif /* !USE_CAIRO && HAVE_XRENDER */ | ||
| 1715 | |||
| 1716 | #ifdef HAVE_X_WINDOWS | ||
| 1717 | if (FRAME_X_DISPLAY (f)) | ||
| 1718 | #endif /* HAVE_X_WINDOWS */ | ||
| 1719 | /* Free resources, then free IMG. */ | ||
| 1720 | img->type->free_img (f, img); | ||
| 1707 | 1721 | ||
| 1708 | /* Free resources, then free IMG. */ | ||
| 1709 | img->type->free_img (f, img); | ||
| 1710 | xfree (img->face_font_family); | 1722 | xfree (img->face_font_family); |
| 1711 | xfree (img); | 1723 | xfree (img); |
| 1712 | } | 1724 | } |
diff --git a/src/xfaces.c b/src/xfaces.c index a558e7328c0..d4583e1a78f 100644 --- a/src/xfaces.c +++ b/src/xfaces.c | |||
| @@ -4569,6 +4569,15 @@ free_realized_face (struct frame *f, struct face *face) | |||
| 4569 | /* Free fontset of FACE if it is ASCII face. */ | 4569 | /* Free fontset of FACE if it is ASCII face. */ |
| 4570 | if (face->fontset >= 0 && face == face->ascii_face) | 4570 | if (face->fontset >= 0 && face == face->ascii_face) |
| 4571 | free_face_fontset (f, face); | 4571 | free_face_fontset (f, face); |
| 4572 | |||
| 4573 | #ifdef HAVE_X_WINDOWS | ||
| 4574 | /* This function might be called with the frame's display | ||
| 4575 | connection deleted, in which event the callbacks below | ||
| 4576 | should not be executed, as they generate X requests. */ | ||
| 4577 | if (FRAME_X_DISPLAY (f)) | ||
| 4578 | return; | ||
| 4579 | #endif /* HAVE_X_WINDOWS */ | ||
| 4580 | |||
| 4572 | if (face->gc) | 4581 | if (face->gc) |
| 4573 | { | 4582 | { |
| 4574 | block_input (); | 4583 | block_input (); |
diff --git a/src/xterm.c b/src/xterm.c index 5e5eb6269e4..e08ffd15b18 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -29428,6 +29428,17 @@ x_free_frame_resources (struct frame *f) | |||
| 29428 | xi_unlink_touch_points (f); | 29428 | xi_unlink_touch_points (f); |
| 29429 | #endif | 29429 | #endif |
| 29430 | 29430 | ||
| 29431 | /* We must free faces before destroying windows because some | ||
| 29432 | font-driver (e.g. xft) access a window while finishing a face. | ||
| 29433 | |||
| 29434 | This function must be called to remove this frame's fontsets from | ||
| 29435 | Vfontset_list, and is itself responsible for not issuing X requests | ||
| 29436 | if the connection has already been terminated. Otherwise, a future | ||
| 29437 | call to a function that iterates over all existing fontsets might | ||
| 29438 | crash, as they are not prepared to receive dead frames. | ||
| 29439 | (bug#66151) */ | ||
| 29440 | free_frame_faces (f); | ||
| 29441 | |||
| 29431 | /* If a display connection is dead, don't try sending more | 29442 | /* If a display connection is dead, don't try sending more |
| 29432 | commands to the X server. */ | 29443 | commands to the X server. */ |
| 29433 | if (dpyinfo->display) | 29444 | if (dpyinfo->display) |
| @@ -29437,10 +29448,6 @@ x_free_frame_resources (struct frame *f) | |||
| 29437 | if (f->pointer_invisible) | 29448 | if (f->pointer_invisible) |
| 29438 | XTtoggle_invisible_pointer (f, 0); | 29449 | XTtoggle_invisible_pointer (f, 0); |
| 29439 | 29450 | ||
| 29440 | /* We must free faces before destroying windows because some | ||
| 29441 | font-driver (e.g. xft) access a window while finishing a | ||
| 29442 | face. */ | ||
| 29443 | free_frame_faces (f); | ||
| 29444 | tear_down_x_back_buffer (f); | 29451 | tear_down_x_back_buffer (f); |
| 29445 | 29452 | ||
| 29446 | if (f->output_data.x->icon_desc) | 29453 | if (f->output_data.x->icon_desc) |