unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: martin rudalics <rudalics@gmx.at>
To: Eli Zaretskii <eliz@gnu.org>
Cc: enometh@meer.net, 39977@debbugs.gnu.org
Subject: bug#39977: 28.0.50; Unhelpful stack trace
Date: Sun, 22 Mar 2020 19:20:33 +0100	[thread overview]
Message-ID: <88e06868-cfc2-7109-b5ea-71fea3aa897e@gmx.at> (raw)
In-Reply-To: <838sjtetmp.fsf@gnu.org>

[-- Attachment #1: Type: text/plain, Size: 2699 bytes --]

 >> Not really.  It's easy for delete_frame to refuse deleting a frame right
 >> at the beginning.  But once it has accepted a deletion, it might become
 >> hard to deal with all the consequences.
 >
 > I don't think I understand where you are going with this.

Once an initial frame has been created, Lisp code should be always able
to rely on the truth of

(and (frame-live-p (selected-frame))
      (window-live-p (selected-window))
      (eq (frame-selected-window (selected-frame))
	 (selected-window)))

Whenever this basic invariant is violated, there is no guarantee that
frame and window management will produce correct results.  Currently,
this invariance is no longer guaranteed if Lisp code is allowed to
manipulate frames and windows arbitrarily while processing the mode line
or the frame title.  IMO there are three possible ways to deal with this
problem:

(1) Let the redisplay code handle it.

(2) Let the frame and window management handle it by disallowing such
operations while they are issued by the mode line or frame title
processing code.

(3) Ignore it and let the frame/window management routines catch up with
it later.

Using (1) way my initial idea.  The patch I proposed handles simple
cases like Madhu's bug.  It will certainly not handle more sophisticated
cases where, for example, an application kills two frames in a row.

(2) is by far the most simple and reliable approach but it will restrict
applications in what they are allowed to do when processing a mode line
or frame title.

(3) means that frame/window management proceeds in a non-deterministic
fashion as long as it has not detected that its basic invariant has been
violated.

 > This isn't about trust.  This is about letting users' Lisp do anything
 > they want as long as the results allow redisplay to continue after
 > that Lisp returns.  I don't think it's right to disallow certain
 > actions just because they _might_ cause problems.

You again care about redisplay only.  Which means that frame/window
management is second-class as far as safety is concerned.

 >>   > No, they are there in cases where we simply don't know how to
 >>   > continue.
 >>
 >> If that's the reason, then SELECTED_FRAME can easily set selected_frame
 >> to some live frame and continue.
 >
 > Something like that, yes.

I attach a patch that does that.  If you try it with a recipe like
loading


(defvar foo
   '(:eval
     (when (> (length (frame-list)) 1)
       (delete-frame (next-frame)))))

(setq-default mode-line-format foo)

(make-frame)


with emacs -Q you will see that while it works around the crash it still
produces a

Wrong type argument: window-live-p, #<window 3>

error in redisplay.

martin

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: SELECTD_FRAME.diff --]
[-- Type: text/x-patch; name="SELECTD_FRAME.diff", Size: 1951 bytes --]

--- a/src/frame.c
+++ b/src/frame.c
@@ -1843,6 +1843,36 @@ other_frames (struct frame *f, bool invisible, bool force)
   return false;
 }
 
+
+/** Select some live frame.  */
+bool
+select_some_frame (void)
+{
+  Lisp_Object tail;
+  Lisp_Object frame UNINIT;
+
+  FOR_EACH_FRAME (tail, frame)
+    {
+      struct frame *f = XFRAME (frame);
+
+      if (!FRAME_PARENT_FRAME (f) && !FRAME_TOOLTIP_P (f))
+	{
+	  /* Select FRAME without switching to it.  This sets up the
+	     selected frame and the selected window and avoids aborting
+	     as when redisplay selects a dead frame (Bug#39977).  */
+	  selected_frame = frame;
+	  if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f)))
+	    FRAME_SELECTED_WINDOW (f) = Fframe_first_window (frame);
+	  selected_window = FRAME_SELECTED_WINDOW (f);
+
+	  return true;
+	}
+    }
+
+  return false;
+}
+
+
 /* Make sure that minibuf_window doesn't refer to FRAME's minibuffer
    window.  Preferably use the selected frame's minibuffer window
    instead.  If the selected frame doesn't have one, get some other
diff --git a/src/frame.h b/src/frame.h
index a54b8623e5..807938fd9f 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -1363,14 +1363,17 @@ window_system_available (struct frame *f)
 
 extern Lisp_Object Vframe_list;
 
+bool select_some_frame (void);
+
 /* Value is a pointer to the selected frame.  If the selected frame
    isn't live, abort.  */
 
 #define SELECTED_FRAME()				\
-     ((FRAMEP (selected_frame)				\
-       && FRAME_LIVE_P (XFRAME (selected_frame)))	\
-      ? XFRAME (selected_frame)				\
-      : (emacs_abort (), (struct frame *) 0))
+  (((FRAMEP (selected_frame)				\
+     && FRAME_LIVE_P (XFRAME (selected_frame)))		\
+    || select_some_frame ())				\
+   ? XFRAME (selected_frame)				\
+   : (emacs_abort (), (struct frame *) 0))
 
 \f
 /***********************************************************************

  reply	other threads:[~2020-03-22 18:20 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-07 17:43 bug#39977: 28.0.50; Unhelpful stack trace Madhu
2020-03-07 18:50 ` Eli Zaretskii
2020-03-13  9:55   ` Eli Zaretskii
2020-03-13 16:28     ` martin rudalics
2020-03-13 19:43       ` Eli Zaretskii
2020-03-14  8:48         ` martin rudalics
2020-03-14 10:10           ` Eli Zaretskii
2020-03-14 10:37             ` martin rudalics
2020-03-14 18:55               ` martin rudalics
2020-03-14 20:09                 ` Eli Zaretskii
2020-03-15 17:49                   ` martin rudalics
2020-03-15 18:41                     ` Eli Zaretskii
2020-03-16  9:24                       ` martin rudalics
2020-03-16 15:33                         ` Eli Zaretskii
2020-03-17  9:38                           ` martin rudalics
2020-03-17 15:51                             ` Eli Zaretskii
2020-03-17 17:31                               ` martin rudalics
2020-03-17 17:45                                 ` Eli Zaretskii
2020-03-17 18:39                                   ` martin rudalics
2020-03-17 19:41                                     ` Eli Zaretskii
2020-03-18  9:12                                       ` martin rudalics
2020-03-18 14:53                                         ` Eli Zaretskii
2020-03-18 18:48                                           ` martin rudalics
2020-03-18 19:36                                             ` Eli Zaretskii
2020-03-19  8:55                                               ` martin rudalics
2020-03-19 14:33                                                 ` Eli Zaretskii
2020-03-21  9:32                                                   ` martin rudalics
2020-03-21 13:15                                                     ` Eli Zaretskii
2020-03-22 18:20                                                       ` martin rudalics [this message]
2020-03-23 14:48                                                         ` Eli Zaretskii
2020-03-24  9:45                                                           ` martin rudalics
2020-03-28  8:23                                                             ` Eli Zaretskii
2020-03-28 18:38                                                               ` martin rudalics
2020-04-03 16:32                                                                 ` martin rudalics
2020-04-10 11:51                                                                   ` Madhu
2020-09-30 15:06                                                                   ` Lars Ingebrigtsen
2020-09-30 15:31                                                                     ` Eli Zaretskii
2020-09-30 17:29                                                                       ` martin rudalics
2020-10-01  0:01                                                                         ` Lars Ingebrigtsen
2020-10-01  4:37                                                                           ` Madhu
2020-03-19  3:48                                             ` Madhu
2020-03-16  2:42                     ` Madhu
2020-03-16  9:25                       ` martin rudalics

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=88e06868-cfc2-7109-b5ea-71fea3aa897e@gmx.at \
    --to=rudalics@gmx.at \
    --cc=39977@debbugs.gnu.org \
    --cc=eliz@gnu.org \
    --cc=enometh@meer.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).