To: vim_dev@googlegroups.com Subject: Patch 7.4.1254 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.4.1254 Problem: Opening a second channel causes a crash. (Ken Takata) Solution: Don't re-allocate the array with channels. Files: src/channel.c, src/testdir/test_channel.vim, src/testdir/test_channel.py *** ../vim-7.4.1253/src/channel.c 2016-02-03 21:32:39.171071570 +0100 --- src/channel.c 2016-02-03 23:10:39.309099840 +0100 *************** *** 133,154 **** add_channel(void) { int idx; - channel_T *new_channels; channel_T *ch; if (channels != NULL) for (idx = 0; idx < channel_count; ++idx) if (channels[idx].ch_fd < 0) /* re-use a closed channel slot */ return idx; ! if (channel_count == MAX_OPEN_CHANNELS) ! return -1; ! new_channels = (channel_T *)alloc(sizeof(channel_T) * (channel_count + 1)); ! if (new_channels == NULL) ! return -1; ! if (channels != NULL) ! mch_memmove(new_channels, channels, sizeof(channel_T) * channel_count); ! channels = new_channels; ch = &channels[channel_count]; (void)vim_memset(ch, 0, sizeof(channel_T)); --- 133,157 ---- add_channel(void) { int idx; channel_T *ch; if (channels != NULL) + { for (idx = 0; idx < channel_count; ++idx) if (channels[idx].ch_fd < 0) /* re-use a closed channel slot */ return idx; ! if (channel_count == MAX_OPEN_CHANNELS) ! return -1; ! } ! else ! { ! channels = (channel_T *)alloc((int)sizeof(channel_T) ! * MAX_OPEN_CHANNELS); ! if (channels == NULL) ! return -1; ! } ! ch = &channels[channel_count]; (void)vim_memset(ch, 0, sizeof(channel_T)); *** ../vim-7.4.1253/src/testdir/test_channel.vim 2016-02-03 22:39:46.488694762 +0100 --- src/testdir/test_channel.vim 2016-02-03 23:17:07.476990166 +0100 *************** *** 17,22 **** --- 17,24 ---- finish endif + let s:port = -1 + func s:start_server() " The Python program writes the port number in Xportnr. call delete("Xportnr") *************** *** 49,57 **** call assert_false(1, "Can't start test_channel.py") return -1 endif ! let port = l[0] ! let handle = ch_open('localhost:' . port, 'json') return handle endfunc --- 51,59 ---- call assert_false(1, "Can't start test_channel.py") return -1 endif ! let s:port = l[0] ! let handle = ch_open('localhost:' . s:port, 'json') return handle endfunc *************** *** 93,98 **** --- 95,118 ---- call s:kill_server() endfunc + + " Test that we can open two channels. + func Test_two_channels() + let handle = s:start_server() + if handle < 0 + return + endif + call assert_equal('got it', ch_sendexpr(handle, 'hello!')) + + let newhandle = ch_open('localhost:' . s:port, 'json') + call assert_equal('got it', ch_sendexpr(newhandle, 'hello!')) + call assert_equal('got it', ch_sendexpr(handle, 'hello!')) + + call ch_close(handle) + call assert_equal('got it', ch_sendexpr(newhandle, 'hello!')) + + call s:kill_server() + endfunc " Test that a server crash is handled gracefully. func Test_server_crash() *** ../vim-7.4.1253/src/testdir/test_channel.py 2016-02-03 22:39:46.488694762 +0100 --- src/testdir/test_channel.py 2016-02-03 23:22:50.329361729 +0100 *************** *** 24,37 **** # Python 2 import SocketServer as socketserver - thesocket = None - class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler): def handle(self): print("=== socket opened ===") - global thesocket - thesocket = self.request while True: try: received = self.request.recv(4096).decode('utf-8') --- 24,33 ---- *************** *** 77,95 **** cmd = '["ex","call append(\\"$\\",\\"added1\\")"]' cmd += '["ex","call append(\\"$\\",\\"added2\\")"]' print("sending: {}".format(cmd)) ! thesocket.sendall(cmd.encode('utf-8')) response = "ok" elif decoded[1] == 'eval-works': # Send an eval request. We ignore the response. cmd = '["eval","\\"foo\\" . 123", -1]' print("sending: {}".format(cmd)) ! thesocket.sendall(cmd.encode('utf-8')) response = "ok" elif decoded[1] == 'eval-fails': # Send an eval request that will fail. cmd = '["eval","xxx", -2]' print("sending: {}".format(cmd)) ! thesocket.sendall(cmd.encode('utf-8')) response = "ok" elif decoded[1] == 'eval-result': # Send back the last received eval result. --- 73,91 ---- cmd = '["ex","call append(\\"$\\",\\"added1\\")"]' cmd += '["ex","call append(\\"$\\",\\"added2\\")"]' print("sending: {}".format(cmd)) ! self.request.sendall(cmd.encode('utf-8')) response = "ok" elif decoded[1] == 'eval-works': # Send an eval request. We ignore the response. cmd = '["eval","\\"foo\\" . 123", -1]' print("sending: {}".format(cmd)) ! self.request.sendall(cmd.encode('utf-8')) response = "ok" elif decoded[1] == 'eval-fails': # Send an eval request that will fail. cmd = '["eval","xxx", -2]' print("sending: {}".format(cmd)) ! self.request.sendall(cmd.encode('utf-8')) response = "ok" elif decoded[1] == 'eval-result': # Send back the last received eval result. *************** *** 105,118 **** encoded = json.dumps([decoded[0], response]) print("sending: {}".format(encoded)) ! thesocket.sendall(encoded.encode('utf-8')) # Negative numbers are used for "eval" responses. elif decoded[0] < 0: last_eval = decoded - thesocket = None - class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer): pass --- 101,112 ---- encoded = json.dumps([decoded[0], response]) print("sending: {}".format(encoded)) ! self.request.sendall(encoded.encode('utf-8')) # Negative numbers are used for "eval" responses. elif decoded[0] < 0: last_eval = decoded class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer): pass *** ../vim-7.4.1253/src/version.c 2016-02-03 22:39:46.488694762 +0100 --- src/version.c 2016-02-03 23:24:05.604565259 +0100 *************** *** 744,745 **** --- 744,747 ---- { /* Add new patch number below this line */ + /**/ + 1254, /**/ -- The difference between theory and practice, is that in theory, there is no difference between theory and practice. /// 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 ///