To: vim_dev@googlegroups.com Subject: Patch 7.4.1493 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.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. Files: src/channel.c, src/testdir/test_channel.vim, src/testdir/test_channel.py *** ../vim-7.4.1492/src/channel.c 2016-03-03 22:51:36.133809707 +0100 --- src/channel.c 2016-03-05 19:56:49.052816399 +0100 *************** *** 1480,1486 **** 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; char_u *callback = NULL; buf_T *buffer = NULL; --- 1480,1486 ---- 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; char_u *callback = NULL; buf_T *buffer = NULL; *************** *** 1488,1494 **** /* this channel is handled elsewhere (netbeans) */ return FALSE; ! /* use a message-specific callback, part callback or channel callback */ if (cbitem != NULL) callback = cbitem->cq_callback; else if (channel->ch_part[part].ch_callback != NULL) --- 1488,1497 ---- /* this channel is handled elsewhere (netbeans) */ return FALSE; ! /* 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,1625 **** int done = FALSE; /* invoke the one-time callback with the matching nr */ ! while (cbitem != NULL) ! { 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); } --- 1613,1625 ---- int done = FALSE; /* invoke the one-time callback with the matching nr */ ! 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; } if (!done) ch_logn(channel, "Dropping message %d without callback", seq_nr); } *** ../vim-7.4.1492/src/testdir/test_channel.vim 2016-03-03 22:51:36.137809664 +0100 --- src/testdir/test_channel.vim 2016-03-05 20:41:43.332603983 +0100 *************** *** 294,299 **** --- 294,365 ---- """"""""" + 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 *** ../vim-7.4.1492/src/testdir/test_channel.py 2016-03-03 19:34:58.221362693 +0100 --- src/testdir/test_channel.py 2016-03-05 19:29:42.673795211 +0100 *************** *** 143,148 **** --- 143,153 ---- 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() *** ../vim-7.4.1492/src/version.c 2016-03-05 17:41:43.113188948 +0100 --- src/version.c 2016-03-05 20:53:06.989418512 +0100 *************** *** 745,746 **** --- 745,748 ---- { /* Add new patch number below this line */ + /**/ + 1493, /**/ -- At some point in the project somebody will start whining about the need to determine the project "requirements". This involves interviewing people who don't know what they want but, curiously, know exactly when they need it. (Scott Adams - The Dilbert principle) /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///