# HG changeset patch # User Christian Brabandt # Date 1454538604 -3600 # Node ID 54602dcac2076a7a765e5af7febf2f621c392bfa # Parent 72085904c404333816620574838e42e2da115c6b commit https://github.com/vim/vim/commit/3b05b135e3ee4cfd59983fd63461e8f7642c1713 Author: Bram Moolenaar Date: Wed Feb 3 23:25:07 2016 +0100 patch 7.4.1254 Problem: Opening a second channel causes a crash. (Ken Takata) Solution: Don't re-allocate the array with channels. diff --git a/src/channel.c b/src/channel.c --- a/src/channel.c +++ b/src/channel.c @@ -133,22 +133,25 @@ FILE *debugfd = NULL; 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; + 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)); diff --git a/src/testdir/test_channel.py b/src/testdir/test_channel.py --- a/src/testdir/test_channel.py +++ b/src/testdir/test_channel.py @@ -24,14 +24,10 @@ except ImportError: # 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') @@ -77,19 +73,19 @@ class ThreadedTCPRequestHandler(socketse cmd = '["ex","call append(\\"$\\",\\"added1\\")"]' cmd += '["ex","call append(\\"$\\",\\"added2\\")"]' print("sending: {}".format(cmd)) - thesocket.sendall(cmd.encode('utf-8')) + 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)) - thesocket.sendall(cmd.encode('utf-8')) + 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)) - thesocket.sendall(cmd.encode('utf-8')) + self.request.sendall(cmd.encode('utf-8')) response = "ok" elif decoded[1] == 'eval-result': # Send back the last received eval result. @@ -105,14 +101,12 @@ class ThreadedTCPRequestHandler(socketse encoded = json.dumps([decoded[0], response]) print("sending: {}".format(encoded)) - thesocket.sendall(encoded.encode('utf-8')) + self.request.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 diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim --- a/src/testdir/test_channel.vim +++ b/src/testdir/test_channel.vim @@ -17,6 +17,8 @@ else finish endif +let s:port = -1 + func s:start_server() " The Python program writes the port number in Xportnr. call delete("Xportnr") @@ -49,9 +51,9 @@ func s:start_server() call assert_false(1, "Can't start test_channel.py") return -1 endif - let port = l[0] + let s:port = l[0] - let handle = ch_open('localhost:' . port, 'json') + let handle = ch_open('localhost:' . s:port, 'json') return handle endfunc @@ -94,6 +96,24 @@ func Test_communicate() 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() let handle = s:start_server() diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -743,6 +743,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1254, +/**/ 1253, /**/ 1252,