To: vim_dev@googlegroups.com Subject: Patch 7.4.1483 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.4.1483 Problem: A one-time callback is not used for a raw channel. Solution: Use a one-time callback when it exists. Files: src/channel.c, src/testdir/test_channel.vim, src/testdir/test_channel.py *** ../vim-7.4.1482/src/channel.c 2016-03-02 21:16:56.025809799 +0100 --- src/channel.c 2016-03-03 18:49:48.409042489 +0100 *************** *** 1390,1395 **** --- 1390,1412 ---- } } + static void + invoke_one_time_callback( + channel_T *channel, + cbq_T *cbhead, + cbq_T *item, + typval_T *argv) + { + ch_logs(channel, "Invoking one-time callback %s", + (char *)item->cq_callback); + /* Remove the item from the list first, if the callback + * invokes ch_close() the list will be cleared. */ + remove_cb_node(cbhead, item); + invoke_callback(channel, item->cq_callback, argv); + vim_free(item->cq_callback); + vim_free(item); + } + /* * Invoke a callback for "channel"/"part" if needed. * Return TRUE when a message was handled, there might be another one. *************** *** 1402,1407 **** --- 1419,1426 ---- typval_T argv[CH_JSON_MAX_ARGS]; 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; *************** *** 1409,1415 **** /* this channel is handled elsewhere (netbeans) */ return FALSE; ! if (channel->ch_part[part].ch_callback != NULL) callback = channel->ch_part[part].ch_callback; else callback = channel->ch_callback; --- 1428,1437 ---- /* 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) callback = channel->ch_part[part].ch_callback; else callback = channel->ch_callback; *************** *** 1525,1551 **** if (seq_nr > 0) { - cbq_T *head = &channel->ch_part[part].ch_cb_head; - cbq_T *item = head->cq_next; int done = FALSE; /* invoke the one-time callback with the matching nr */ ! while (item != NULL) { ! if (item->cq_seq_nr == seq_nr) { ! ch_logs(channel, "Invoking one-time callback %s", ! (char *)item->cq_callback); ! /* Remove the item from the list first, if the callback ! * invokes ch_close() the list will be cleared. */ ! remove_cb_node(head, item); ! invoke_callback(channel, item->cq_callback, argv); ! vim_free(item->cq_callback); ! vim_free(item); done = TRUE; break; } ! item = item->cq_next; } if (!done) ch_logn(channel, "Dropping message %d without callback", seq_nr); --- 1547,1564 ---- if (seq_nr > 0) { 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); *************** *** 1599,1609 **** } } } if (callback != NULL) { ! /* invoke the channel callback */ ! ch_logs(channel, "Invoking channel callback %s", (char *)callback); ! invoke_callback(channel, callback, argv); } } else --- 1612,1629 ---- } } } + if (callback != NULL) { ! if (cbitem != NULL) ! invoke_one_time_callback(channel, cbhead, cbitem, argv); ! else ! { ! /* invoke the channel callback */ ! ch_logs(channel, "Invoking channel callback %s", ! (char *)callback); ! invoke_callback(channel, callback, argv); ! } } } else *** ../vim-7.4.1482/src/testdir/test_channel.vim 2016-03-03 18:09:06.013997633 +0100 --- src/testdir/test_channel.vim 2016-03-03 19:21:06.045874189 +0100 *************** *** 257,262 **** --- 257,264 ---- call s:run_server('s:server_crash') endfunc + """"""""" + let s:reply = "" func s:Handler(chan, msg) unlet s:reply *************** *** 290,295 **** --- 292,352 ---- unlet s:chopt.callback endfunc + """"""""" + + let s:reply1 = "" + func s:HandleRaw1(chan, msg) + unlet s:reply1 + let s:reply1 = a:msg + endfunc + + let s:reply2 = "" + func s:HandleRaw2(chan, msg) + unlet s:reply2 + let s:reply2 = a:msg + endfunc + + let s:reply3 = "" + func s:HandleRaw3(chan, msg) + unlet s:reply3 + let s:reply3 = a:msg + endfunc + + func s:raw_one_time_callback(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 + call ch_setoptions(handle, {'mode': 'raw'}) + + " The message are sent raw, we do our own JSON strings here. + call ch_sendraw(handle, "[1, \"hello!\"]", {'callback': 's:HandleRaw1'}) + sleep 10m + call assert_equal("[1, \"got it\"]", s:reply1) + call ch_sendraw(handle, "[2, \"echo something\"]", {'callback': 's:HandleRaw2'}) + call ch_sendraw(handle, "[3, \"wait a bit\"]", {'callback': 's:HandleRaw3'}) + sleep 10m + call assert_equal("[2, \"something\"]", s:reply2) + " wait for up to 500 msec for the 200 msec delayed reply + for i in range(50) + sleep 10m + if s:reply3 != '' + break + endif + endfor + call assert_equal("[3, \"waited\"]", s:reply3) + endfunc + + func Test_raw_one_time_callback() + call ch_logfile('channellog', 'w') + call ch_log('Test_raw_one_time_callback()') + call s:run_server('s:raw_one_time_callback') + call ch_logfile('') + endfunc + + """"""""" + " Test that trying to connect to a non-existing port fails quickly. func Test_connect_waittime() call ch_log('Test_connect_waittime()') *************** *** 325,330 **** --- 382,389 ---- endtry endfunc + """"""""" + func Test_raw_pipe() if !has('job') return *** ../vim-7.4.1482/src/testdir/test_channel.py 2016-02-23 13:20:18.466462173 +0100 --- src/testdir/test_channel.py 2016-03-03 19:19:11.183057626 +0100 *************** *** 62,67 **** --- 62,70 ---- if decoded[1] == 'hello!': # simply send back a string response = "got it" + elif decoded[1].startswith("echo "): + # send back the argument + response = decoded[1][5:] elif decoded[1] == 'make change': # Send two ex commands at the same time, before # replying to the request. *** ../vim-7.4.1482/src/version.c 2016-03-03 18:09:06.013997633 +0100 --- src/version.c 2016-03-03 18:48:10.190033280 +0100 *************** *** 745,746 **** --- 745,748 ---- { /* Add new patch number below this line */ + /**/ + 1483, /**/ -- A village. Sound of chanting of Latin canon, punctuated by short, sharp cracks. It comes nearer. We see it is a line of MONKS ala SEVENTH SEAL flagellation scene, chanting and banging themselves on the foreheads with wooden boards. "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// 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 ///