summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-02-08 23:23:42 +0100
committerBram Moolenaar <Bram@vim.org>2016-02-08 23:23:42 +0100
commite56bf15c163a921ce9e1c09c0d5b3a03efc63324 (patch)
tree1957c1a0ab9211500ca2f07cf92b6d59057c7022
parent2fc83fcd1d6dfd4728a2ef70e2316f79203c7ee0 (diff)
patch 7.4.1293v7.4.1293
Problem: Sometimes a channel may hang waiting for a message that was already discarded. (Ken Takata) Solution: Store the ID of the message blocking on in the channel.
-rw-r--r--src/channel.c26
-rw-r--r--src/version.c2
2 files changed, 20 insertions, 8 deletions
diff --git a/src/channel.c b/src/channel.c
index 5e4d1825c3..50dd18087c 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -116,6 +116,8 @@ typedef struct {
void (*ch_close_cb)(void); /* callback for when channel is closed */
+ int ch_block_id; /* ID that channel_read_json_block() is
+ waiting for */
char_u *ch_callback; /* function to call when a msg is not handled */
cbq_T ch_cb_head; /* dummy node for pre-request callbacks */
@@ -765,15 +767,17 @@ remove_json_node(jsonq_T *node)
/*
* Get a message from the JSON queue for channel "ch_idx".
* When "id" is positive it must match the first number in the list.
- * When "id" is zero or negative jut get the first message.
+ * When "id" is zero or negative jut get the first message. But not the one
+ * with id ch_block_id.
* Return OK when found and return the value in "rettv".
* Return FAIL otherwise.
*/
static int
channel_get_json(int ch_idx, int id, typval_T **rettv)
{
- jsonq_T *head = &channels[ch_idx].ch_json_head;
- jsonq_T *item = head->next;
+ channel_T *channel = &channels[ch_idx];
+ jsonq_T *head = &channel->ch_json_head;
+ jsonq_T *item = head->next;
while (item != head)
{
@@ -781,7 +785,8 @@ channel_get_json(int ch_idx, int id, typval_T **rettv)
typval_T *tv = &l->lv_first->li_tv;
if ((id > 0 && tv->v_type == VAR_NUMBER && tv->vval.v_number == id)
- || id <= 0)
+ || (id <= 0 && (tv->v_type != VAR_NUMBER
+ || tv->vval.v_number != channel->ch_block_id)))
{
*rettv = item->value;
remove_json_node(item);
@@ -1291,15 +1296,20 @@ channel_read_block(int idx)
int
channel_read_json_block(int ch_idx, int id, typval_T **rettv)
{
- int more;
+ int more;
+ channel_T *channel = &channels[ch_idx];
+ channel->ch_block_id = id;
for (;;)
{
more = channel_parse_json(ch_idx);
/* search for messsage "id" */
if (channel_get_json(ch_idx, id, rettv) == OK)
+ {
+ channel->ch_block_id = 0;
return OK;
+ }
if (!more)
{
@@ -1309,13 +1319,13 @@ channel_read_json_block(int ch_idx, int id, typval_T **rettv)
continue;
/* Wait for up to the channel timeout. */
- if (channels[ch_idx].ch_fd < 0
- || channel_wait(channels[ch_idx].ch_fd,
- channels[ch_idx].ch_timeout) == FAIL)
+ if (channel->ch_fd < 0 || channel_wait(channel->ch_fd,
+ channel->ch_timeout) == FAIL)
break;
channel_read(ch_idx);
}
}
+ channel->ch_block_id = 0;
return FAIL;
}
diff --git a/src/version.c b/src/version.c
index d9f0807191..b5bf05ea0f 100644
--- a/src/version.c
+++ b/src/version.c
@@ -748,6 +748,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1293,
+/**/
1292,
/**/
1291,