diff options
| author | Pip Cet | 2026-04-10 11:35:22 +0000 |
|---|---|---|
| committer | Pip Cet | 2026-04-10 18:16:54 +0000 |
| commit | 2edcc6d4223a2837e594ff83c13832533b5e3ef8 (patch) | |
| tree | a998857293d3bdbd78dcf7525fa7abc49331bb43 /src | |
| parent | 708759324e2314eb912ddb9758cabecd16469ffe (diff) | |
| download | emacs-2edcc6d4223a2837e594ff83c13832533b5e3ef8.tar.gz emacs-2edcc6d4223a2837e594ff83c13832533b5e3ef8.zip | |
Ensure selected_frame isn't the deleted frame (bug#80789)
The previous code would sometimes exit the loop with frame1 set to the
last considered frame, even if that wasn't a suitable frame to switch
to.
* src/frame.c (delete_frame): Reset 'frame1' in the loops if we don't
match the break condition, so we don't think we've found a suitable
replacement frame if we haven't. Error if, for some reason, that
fails.
Diffstat (limited to 'src')
| -rw-r--r-- | src/frame.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/src/frame.c b/src/frame.c index d0d02eaeb1f..2c0a27cf47c 100644 --- a/src/frame.c +++ b/src/frame.c | |||
| @@ -2733,8 +2733,6 @@ delete_frame (Lisp_Object frame, Lisp_Object force) | |||
| 2733 | error ("Attempt to delete the only frame"); | 2733 | error ("Attempt to delete the only frame"); |
| 2734 | } | 2734 | } |
| 2735 | 2735 | ||
| 2736 | /* At this point, we are committed to deleting the frame. | ||
| 2737 | There is no more chance for errors to prevent it. */ | ||
| 2738 | sf = SELECTED_FRAME (); | 2736 | sf = SELECTED_FRAME (); |
| 2739 | /* Don't let the frame remain selected. */ | 2737 | /* Don't let the frame remain selected. */ |
| 2740 | if (f == sf) | 2738 | if (f == sf) |
| @@ -2754,7 +2752,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force) | |||
| 2754 | frames on the same terminal as FRAME, excluding FRAME | 2752 | frames on the same terminal as FRAME, excluding FRAME |
| 2755 | which we are about to delete. */ | 2753 | which we are about to delete. */ |
| 2756 | frame1 = safe_calln (Qget_mru_frame, Qvisible, Qnil, frame); | 2754 | frame1 = safe_calln (Qget_mru_frame, Qvisible, Qnil, frame); |
| 2757 | if (!NILP (frame1)) | 2755 | if (FRAMEP (frame1)) |
| 2758 | { | 2756 | { |
| 2759 | struct frame *f1 = XFRAME (frame1); | 2757 | struct frame *f1 = XFRAME (frame1); |
| 2760 | 2758 | ||
| @@ -2764,6 +2762,8 @@ delete_frame (Lisp_Object frame, Lisp_Object force) | |||
| 2764 | || EQ (frame1, frame)) | 2762 | || EQ (frame1, frame)) |
| 2765 | frame1 = Qnil; | 2763 | frame1 = Qnil; |
| 2766 | } | 2764 | } |
| 2765 | else | ||
| 2766 | frame1 = Qnil; | ||
| 2767 | } | 2767 | } |
| 2768 | 2768 | ||
| 2769 | if (NILP (frame1)) | 2769 | if (NILP (frame1)) |
| @@ -2783,6 +2783,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force) | |||
| 2783 | && FRAME_TERMINAL (f) == FRAME_TERMINAL (f1) | 2783 | && FRAME_TERMINAL (f) == FRAME_TERMINAL (f1) |
| 2784 | && FRAME_VISIBLE_P (f1)) | 2784 | && FRAME_VISIBLE_P (f1)) |
| 2785 | break; | 2785 | break; |
| 2786 | frame1 = Qnil; | ||
| 2786 | } | 2787 | } |
| 2787 | 2788 | ||
| 2788 | /* If there is none, find *some* other frame. */ | 2789 | /* If there is none, find *some* other frame. */ |
| @@ -2805,6 +2806,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force) | |||
| 2805 | } | 2806 | } |
| 2806 | break; | 2807 | break; |
| 2807 | } | 2808 | } |
| 2809 | frame1 = Qnil; | ||
| 2808 | } | 2810 | } |
| 2809 | } | 2811 | } |
| 2810 | #ifdef NS_IMPL_COCOA | 2812 | #ifdef NS_IMPL_COCOA |
| @@ -2821,8 +2823,18 @@ delete_frame (Lisp_Object frame, Lisp_Object force) | |||
| 2821 | #endif | 2823 | #endif |
| 2822 | } | 2824 | } |
| 2823 | 2825 | ||
| 2824 | do_switch_frame (frame1, 0, 1, Qnil); | 2826 | if (FRAMEP (frame1) && XFRAME (frame1) != f) |
| 2827 | do_switch_frame (frame1, 0, 1, Qnil); | ||
| 2828 | else if (EQ (force, Qnoelisp)) | ||
| 2829 | { | ||
| 2830 | /* This is the last frame, and it's being forcibly | ||
| 2831 | deleted. There's no way to recover from this. */ | ||
| 2832 | Fkill_emacs (make_fixnum (70), Qnil); | ||
| 2833 | } | ||
| 2834 | else | ||
| 2835 | emacs_abort (); | ||
| 2825 | sf = SELECTED_FRAME (); | 2836 | sf = SELECTED_FRAME (); |
| 2837 | eassert (sf != f); | ||
| 2826 | } | 2838 | } |
| 2827 | } | 2839 | } |
| 2828 | else | 2840 | else |
| @@ -2830,6 +2842,8 @@ delete_frame (Lisp_Object frame, Lisp_Object force) | |||
| 2830 | frame. */ | 2842 | frame. */ |
| 2831 | move_minibuffers_onto_frame (f, selected_frame, true); | 2843 | move_minibuffers_onto_frame (f, selected_frame, true); |
| 2832 | 2844 | ||
| 2845 | /* At this point, we are committed to deleting the frame. | ||
| 2846 | There is no more chance for errors to prevent it. */ | ||
| 2833 | /* Don't let echo_area_window to remain on a deleted frame. */ | 2847 | /* Don't let echo_area_window to remain on a deleted frame. */ |
| 2834 | if (EQ (f->minibuffer_window, echo_area_window)) | 2848 | if (EQ (f->minibuffer_window, echo_area_window)) |
| 2835 | echo_area_window = sf->minibuffer_window; | 2849 | echo_area_window = sf->minibuffer_window; |