Subject: bug#34179: 27.0.50; message hangs when buffer with process visible

From: martin rudalics <[email-masked]>
Date: Mon, 28 Jan 2019 19:38:15 +0100

> I'm seeing too.

It's a wild goose chase where do_switch_frame always wins to shrink
the minbuffer window.  I attached another patch.  Please try again.

Thanks, martin
diff --git a/src/xdisp.c b/src/xdisp.c
index 8649507..a60eb2d 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -540,6 +540,14 @@
 
 static bool message_cleared_p;
 
+/* True means redisplay must not retry.  */
+
+static bool must_finish;
+
+/* True means redisplay has to redisplay the miniwindow.  */
+
+static  bool update_miniwindow_p;
+
 /* A scratch glyph row with contents used for generating truncation
    glyphs.  Also used in direct_output_for_insert.  */
 
@@ -11758,6 +11766,44 @@ static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
     }
 }
 
+
+/* Redisplay echo_area if needed.  Checking message_cleared_p captures
+   the case that the echo area should be cleared.
+
+   Return true if we did redisplay the echo area.  */
+
+static bool
+echo_area_redisplay (void)
+{
+  if ((!NILP (echo_area_buffer[0]) && !display_last_displayed_message_p)
+      || (!NILP (echo_area_buffer[1]) && display_last_displayed_message_p)
+      || (message_cleared_p
+	  && minibuf_level == 0
+	  /* If the mini-window is currently selected, this means the
+	     echo-area doesn't show through.  */
+	  && !MINI_WINDOW_P (XWINDOW (selected_window))))
+    {
+      echo_area_display (false);
+
+      if (message_cleared_p)
+	update_miniwindow_p = true;
+
+      must_finish = true;
+
+      /* If we don't display the current message, don't clear the
+	 message_cleared_p flag, because, if we did, we wouldn't clear
+	 the echo area in the next redisplay which doesn't preserve
+	 the echo area.  */
+      if (!display_last_displayed_message_p)
+	message_cleared_p = false;
+
+      return true;
+    }
+  else
+    return false;
+}
+
+
 /* True if W's buffer was changed but not saved.  */
 
 static bool
@@ -13936,7 +13982,7 @@ static void debug_method_add (struct window *, char const *, ...)
   struct window *sw;
   struct frame *fr;
   bool pending;
-  bool must_finish = false, match_p;
+  bool match_p;
   struct text_pos tlbufpos, tlendpos;
   int number_of_visible_frames;
   ptrdiff_t count;
@@ -13962,11 +14008,11 @@ static void debug_method_add (struct window *, char const *, ...)
      frames.  False, only selected_window is considered.  */
   bool consider_all_windows_p;
 
-  /* True means redisplay has to redisplay the miniwindow.  */
-  bool update_miniwindow_p = false;
-
   TRACE ((stderr, "redisplay_internal %d\n", redisplaying_p));
 
+  must_finish = false;
+  update_miniwindow_p = false;
+
   /* No redisplay if running in batch mode or frame is not yet fully
      initialized, or redisplay is explicitly turned off by setting
      Vinhibit_redisplay.  */
@@ -14117,31 +14163,10 @@ static void debug_method_add (struct window *, char const *, ...)
      the update may have been preempted, so display the echo area
      again here.  Checking message_cleared_p captures the case that
      the echo area should be cleared.  */
-  if ((!NILP (echo_area_buffer[0]) && !display_last_displayed_message_p)
-      || (!NILP (echo_area_buffer[1]) && display_last_displayed_message_p)
-      || (message_cleared_p
-	  && minibuf_level == 0
-	  /* If the mini-window is currently selected, this means the
-	     echo-area doesn't show through.  */
-	  && !MINI_WINDOW_P (XWINDOW (selected_window))))
-    {
-      echo_area_display (false);
-
-      if (message_cleared_p)
-	update_miniwindow_p = true;
-
-      must_finish = true;
-
-      /* If we don't display the current message, don't clear the
-	 message_cleared_p flag, because, if we did, we wouldn't clear
-	 the echo area in the next redisplay which doesn't preserve
-	 the echo area.  */
-      if (!display_last_displayed_message_p)
-	message_cleared_p = false;
-    }
-  else if (EQ (selected_window, minibuf_window)
-	   && (current_buffer->clip_changed || window_outdated (w))
-	   && resize_mini_window (w, false))
+  if (!echo_area_redisplay ()
+      && EQ (selected_window, minibuf_window)
+      && (current_buffer->clip_changed || window_outdated (w))
+      && resize_mini_window (w, false))
     {
       /* Resized active mini-window to fit the size of what it is
          showing if its contents might have changed.  */
@@ -14153,6 +14178,16 @@ static void debug_method_add (struct window *, char const *, ...)
       clear_garbaged_frames ();
     }
 
+  if (!NILP (Vrun_hooks))
+    {
+      run_window_change_functions ();
+
+      /* With multiple frames any do_switch_frame run by a window change
+	 function may have shrunk the echo area.  Rerun echo_area_display
+	 to guard against this.  See Bug#34179.*/
+      echo_area_redisplay ();
+    }
+
   if (windows_or_buffers_changed && !update_mode_lines)
     /* Code that sets windows_or_buffers_changed doesn't distinguish whether
        only the windows's contents needs to be refreshed, or whether the
@@ -14332,18 +14367,6 @@ static void debug_method_add (struct window *, char const *, ...)
 		  && (w = XWINDOW (selected_window)) != sw)
 		goto retry;
 
-	      if (!NILP (Vrun_hooks))
-		{
-		  run_window_change_functions ();
-
-		  /* If windows or buffers changed or selected_window
-		     changed, redisplay again.  */
-		  if ((windows_or_buffers_changed)
-		      || (WINDOWP (selected_window)
-			  && (w = XWINDOW (selected_window)) != sw))
-		    goto retry;
-		}
-
 		/* We used to always goto end_of_redisplay here, but this
 		 isn't enough if we have a blinking cursor.  */
 	      if (w->cursor_off_p == w->last_cursor_off_p)
@@ -14707,18 +14730,6 @@ static void debug_method_add (struct window *, char const *, ...)
 	  && (w = XWINDOW (selected_window)) != sw))
     goto retry;
 
-  if (!NILP (Vrun_hooks))
-    {
-      run_window_change_functions ();
-
-      /* If windows or buffers changed or selected_window changed,
-	 redisplay again.  */
-      if ((windows_or_buffers_changed)
-	  || (WINDOWP (selected_window)
-	      && (w = XWINDOW (selected_window)) != sw))
-	goto retry;
-    }
-
   /* Clear the face and image caches.
 
      We used to do this only if consider_all_windows_p.  But the cache