>> >> (and (frame-live-p (selected-frame)) >> >> (window-live-p (selected-window)) >> >> (eq (frame-selected-window (selected-frame)) >> >> (selected-window))) >> > >> > I agree. But note that selected-frame could switch frames internally, >> > if the last selected frame is dead; as long as selected-frame also >> > adjusts the selected window, the above will still hold. >> >> Do you mean 'select-frame' instead of 'selected-frame'? > > No, I meant selected-frame. So you meant a 'selected-frame' based on the SELECTED_FRAME I proposed. The problem is that that macro won't protect the invariant if it was broken before, for example, by setting the selected window to a dead window as in Madhu's scenario. > Perhaps we should make unwind_format_mode_line less fragile, then. The problematic step happens already at the time we set it up. In a nutshell, Madhu's scenario goes as follows: In display_mode_lines we do Lisp_Object old_selected_window = selected_window; Lisp_Object old_selected_frame = selected_frame; ... display_mode_line (w, CURRENT_MODE_LINE_FACE_ID_3 (sel_w, sel_w, w), NILP (window_mode_line_format) ? BVAR (current_buffer, mode_line_format) : window_mode_line_format); ... XFRAME (new_frame)->selected_window = old_frame_selected_window; selected_frame = old_selected_frame; selected_window = old_selected_window; where display_mode_line deletes both, old_selected_frame and old_selected_window. So we end up with selected_frame and selected_window both referencing dead objects. The subsequent call of gui_consider_frame_title now does record_unwind_protect (unwind_format_mode_line, format_mode_line_unwind_data (f, current_buffer, selected_window, false)); where selected_window is already a dead window. Since in unwind_format_mode_line old_window is non-nil, it will call Fselect_window (old_window, Qt); which first chokes on CHECK_LIVE_WINDOW (window); which is the error reported when emacs does not crash and finally on sf = SELECTED_FRAME (); which crashes emacs due to the fact that selected_frame is dead. In either case, making the unwind_format_mode_line less fragile won't avoid any crash, it might just postpone it. >> And I have no idea yet why we need an extra unwind for restoring >> selected_frame and selected_window. Shouldn't these go hand in hand >> with what unwind_format_mode_line does? Does the one even know >> about the other? > > I don't think I understand what extra unwind are you talking about > here. Can you provide a more specific pointer to the relevant code? I meant the fact that we already do unwind_format_mode_line when formatting the mode line and that function could restore the selected window in a safe way. I'm far from proposing to use that approach when drawing the mode lines, though. Attached find a patch which should solve the more grave problems caused by a function deleting the previously selected frame or window. It intentionally does not change SELECTED_FRAME. Any abort there should be reserved to obscure bugs we have not been able to trace yet. Please read it with your usual care, it took me some time to convince myself that it selects its frame in a reasonable way. On master, I would then like to use restore_selected_window also for gui_consider_frame_title. The overhead caused by that is a great annoyance (especially when debugging frame switching code) and we could then hopefully get rid of the old_window stuff and the Bug#32777 fix as well. What any patch I provide here cannot do is to fix problems when the mode line code deletes the selected window right away. Code like (defvar window (split-window)) (defvar foo '(:eval (if (or (not (window-live-p window)) (eq window (frame-first-window))) (setq window (split-window)) (delete-window window)))) (setq-default mode-line-format foo) will continue to segfault unless you can cure that. I tried to fix it in the spirit of if (!FRAME_LIVE_P (it->f)) signal_error (":eval deleted the frame being displayed", elt); but that just caused emacs to hang. martin