summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-03-05 20:54:36 +0100
committerBram Moolenaar <Bram@vim.org>2016-03-05 20:54:36 +0100
commit5983ad0b038fa689653246cb304fd43e8ae39a78 (patch)
treea1065749450fdcfa5490cd0ad683a7ee33f9a6ed
parent35ca0e7a1cb6e6daef8e0052a8437801226cef19 (diff)
downloadvim-git-7.4.1493.tar.gz
patch 7.4.1493v7.4.1493
Problem: Wrong callback invoked for zero-id messages. Solution: Don't use the first one-time callback when the sequence number doesn't match.
-rw-r--r--src/channel.c12
-rw-r--r--src/testdir/test_channel.py5
-rw-r--r--src/testdir/test_channel.vim66
-rw-r--r--src/version.c2
4 files changed, 79 insertions, 6 deletions
diff --git a/src/channel.c b/src/channel.c
index 74cbd14d8..da13f962c 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -1480,7 +1480,7 @@ may_invoke_callback(channel_T *channel, int part)
int seq_nr = -1;
ch_mode_T ch_mode = channel->ch_part[part].ch_mode;
cbq_T *cbhead = &channel->ch_part[part].ch_cb_head;
- cbq_T *cbitem = cbhead->cq_next;
+ cbq_T *cbitem;
char_u *callback = NULL;
buf_T *buffer = NULL;
@@ -1488,7 +1488,10 @@ may_invoke_callback(channel_T *channel, int part)
/* this channel is handled elsewhere (netbeans) */
return FALSE;
- /* use a message-specific callback, part callback or channel callback */
+ /* Use a message-specific callback, part callback or channel callback */
+ for (cbitem = cbhead->cq_next; cbitem != NULL; cbitem = cbitem->cq_next)
+ if (cbitem->cq_seq_nr == 0)
+ break;
if (cbitem != NULL)
callback = cbitem->cq_callback;
else if (channel->ch_part[part].ch_callback != NULL)
@@ -1610,16 +1613,13 @@ may_invoke_callback(channel_T *channel, int part)
int done = FALSE;
/* invoke the one-time callback with the matching nr */
- while (cbitem != NULL)
- {
+ for (cbitem = cbhead->cq_next; cbitem != NULL; cbitem = cbitem->cq_next)
if (cbitem->cq_seq_nr == seq_nr)
{
invoke_one_time_callback(channel, cbhead, cbitem, argv);
done = TRUE;
break;
}
- cbitem = cbitem->cq_next;
- }
if (!done)
ch_logn(channel, "Dropping message %d without callback", seq_nr);
}
diff --git a/src/testdir/test_channel.py b/src/testdir/test_channel.py
index 02e6ba3ec..a465d65d2 100644
--- a/src/testdir/test_channel.py
+++ b/src/testdir/test_channel.py
@@ -143,6 +143,11 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
print("sending: {}".format(cmd))
self.request.sendall(cmd.encode('utf-8'))
response = ""
+ elif decoded[1] == 'send zero':
+ cmd = '[0,"zero index"]'
+ print("sending: {}".format(cmd))
+ self.request.sendall(cmd.encode('utf-8'))
+ response = "sent zero"
elif decoded[1] == 'close me':
print("closing")
self.request.close()
diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim
index faa89f3e8..3bdfd4cbf 100644
--- a/src/testdir/test_channel.vim
+++ b/src/testdir/test_channel.vim
@@ -294,6 +294,72 @@ endfunc
"""""""""
+let s:ch_reply = ''
+func s:ChHandler(chan, msg)
+ unlet s:ch_reply
+ let s:ch_reply = a:msg
+endfunc
+
+let s:zero_reply = ''
+func s:OneHandler(chan, msg)
+ unlet s:zero_reply
+ let s:zero_reply = a:msg
+endfunc
+
+func s:channel_zero(port)
+ let handle = ch_open('localhost:' . a:port, s:chopt)
+ if ch_status(handle) == "fail"
+ call assert_false(1, "Can't open channel")
+ return
+ endif
+
+ " Check that eval works.
+ call assert_equal('got it', ch_evalexpr(handle, 'hello!'))
+
+ " Check that eval works if a zero id message is sent back.
+ let s:ch_reply = ''
+ call assert_equal('sent zero', ch_evalexpr(handle, 'send zero'))
+ sleep 10m
+ if s:has_handler
+ call assert_equal('zero index', s:ch_reply)
+ else
+ call assert_equal('', s:ch_reply)
+ endif
+
+ " Check that handler works if a zero id message is sent back.
+ let s:ch_reply = ''
+ let s:zero_reply = ''
+ call ch_sendexpr(handle, 'send zero', {'callback': 's:OneHandler'})
+ " Somehow the second message takes a bit of time.
+ for i in range(50)
+ if s:zero_reply == 'sent zero'
+ break
+ endif
+ sleep 10m
+ endfor
+ if s:has_handler
+ call assert_equal('zero index', s:ch_reply)
+ else
+ call assert_equal('', s:ch_reply)
+ endif
+ call assert_equal('sent zero', s:zero_reply)
+endfunc
+
+func Test_zero_reply()
+ call ch_log('Test_zero_reply()')
+ " Run with channel handler
+ let s:has_handler = 1
+ let s:chopt.callback = 's:ChHandler'
+ call s:run_server('s:channel_zero')
+ unlet s:chopt.callback
+
+ " Run without channel handler
+ let s:has_handler = 0
+ call s:run_server('s:channel_zero')
+endfunc
+
+"""""""""
+
let s:reply1 = ""
func s:HandleRaw1(chan, msg)
unlet s:reply1
diff --git a/src/version.c b/src/version.c
index 51c2b810e..fe5d00eda 100644
--- a/src/version.c
+++ b/src/version.c
@@ -744,6 +744,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1493,
+/**/
1492,
/**/
1491,