changeset 28612:352806724e12 v8.2.4830

patch 8.2.4830: possible endless loop if there is unused typahead Commit: https://github.com/vim/vim/commit/23f106efeb64eadd95adee34144f64526aa5f61f Author: Bram Moolenaar <Bram@vim.org> Date: Tue Apr 26 18:52:22 2022 +0100 patch 8.2.4830: possible endless loop if there is unused typahead Problem: Possible endless loop if there is unused typahead. Solution: Only loop when the typeahead changed.
author Bram Moolenaar <Bram@vim.org>
date Tue, 26 Apr 2022 20:00:04 +0200
parents ab50b921aea6
children a56f5442fd9a
files src/channel.c src/version.c
diffstat 2 files changed, 38 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/channel.c
+++ b/src/channel.c
@@ -2029,7 +2029,7 @@ channel_consume(channel_T *channel, ch_p
 
 /*
  * Collapses the first and second buffer for "channel"/"part".
- * Returns FAIL if that is not possible.
+ * Returns FAIL if nothing was done.
  * When "want_nl" is TRUE collapse more buffers until a NL is found.
  * When the channel part mode is "lsp", collapse all the buffers as the http
  * header and the JSON content can be present in multiple buffers.
@@ -2957,6 +2957,17 @@ drop_messages(channel_T *channel, ch_par
 }
 
 /*
+ * Return TRUE if for "channel" / "part" ch_json_head should be used.
+ */
+    static int
+channel_use_json_head(channel_T *channel, ch_part_T part)
+{
+    ch_mode_T	ch_mode = channel->ch_part[part].ch_mode;
+
+    return ch_mode == MODE_JSON || ch_mode == MODE_JS || ch_mode == MODE_LSP;
+}
+
+/*
  * Invoke a callback for "channel"/"part" if needed.
  * This does not redraw but sets channel_need_redraw when redraw is needed.
  * Return TRUE when a message was handled, there might be another one.
@@ -3002,7 +3013,7 @@ may_invoke_callback(channel_T *channel, 
 	buffer = NULL;
     }
 
-    if (ch_mode == MODE_JSON || ch_mode == MODE_JS || ch_mode == MODE_LSP)
+    if (channel_use_json_head(channel, part))
     {
 	listitem_T	*item;
 	int		argc = 0;
@@ -3248,14 +3259,13 @@ channel_is_open(channel_T *channel)
 }
 
 /*
- * Return TRUE if "channel" has JSON or other typeahead.
+ * Return a pointer indicating the readahead.  Can only be compared between
+ * calls.  Returns NULL if there is no readahead.
  */
-    static int
-channel_has_readahead(channel_T *channel, ch_part_T part)
+    static void *
+channel_readahead_pointer(channel_T *channel, ch_part_T part)
 {
-    ch_mode_T	ch_mode = channel->ch_part[part].ch_mode;
-
-    if (ch_mode == MODE_JSON || ch_mode == MODE_JS || ch_mode == MODE_LSP)
+    if (channel_use_json_head(channel, part))
     {
 	jsonq_T   *head = &channel->ch_part[part].ch_json_head;
 
@@ -3264,9 +3274,18 @@ channel_has_readahead(channel_T *channel
 	    // process.
 	    channel_parse_json(channel, part);
 
-	return head->jq_next != NULL;
+	return head->jq_next;
     }
-    return channel_peek(channel, part) != NULL;
+    return channel_peek(channel, part);
+}
+
+/*
+ * Return TRUE if "channel" has JSON or other typeahead.
+ */
+    static int
+channel_has_readahead(channel_T *channel, ch_part_T part)
+{
+    return channel_readahead_pointer(channel, part) != NULL;
 }
 
 /*
@@ -4013,14 +4032,19 @@ channel_read_json_block(
 
 	if (!more)
 	{
+	    void *prev_readahead_ptr = channel_readahead_pointer(channel, part);
+	    void *readahead_ptr;
+
 	    // Handle any other messages in the queue.  If done some more
 	    // messages may have arrived.
 	    if (channel_parse_messages())
 		continue;
 
 	    // channel_parse_messages() may fill the queue with new data to
-	    // process.
-	    if (channel_has_readahead(channel, part))
+	    // process.  Only loop when the readahead changed, otherwise we
+	    // would busy-loop.
+	    readahead_ptr = channel_readahead_pointer(channel, part);
+	    if (readahead_ptr != NULL && readahead_ptr != prev_readahead_ptr)
 		continue;
 
 	    // Wait for up to the timeout.  If there was an incomplete message
--- a/src/version.c
+++ b/src/version.c
@@ -747,6 +747,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    4830,
+/**/
     4829,
 /**/
     4828,