diff options
| author | Thiago de Arruda <tpadilha84@gmail.com> | 2014-10-23 10:16:45 -0300 | 
|---|---|---|
| committer | Thiago de Arruda <tpadilha84@gmail.com> | 2014-10-23 21:19:08 -0300 | 
| commit | d4f78127fb49c61de40a57a5dbf6e51c4fc1449a (patch) | |
| tree | 8fe3e72a39d8ba203b14d6e7489b36b6332b716c /src | |
| parent | b4ec764e8e2dbd4a3ae4f29ed4d321ba51397b19 (diff) | |
| download | rneovim-d4f78127fb49c61de40a57a5dbf6e51c4fc1449a.tar.gz rneovim-d4f78127fb49c61de40a57a5dbf6e51c4fc1449a.tar.bz2 rneovim-d4f78127fb49c61de40a57a5dbf6e51c4fc1449a.zip  | |
msgpack-rpc: Ensure stdio channels are properly closed
When stdio was closed, parse_msgpack was called with eof == true, with caused a
free_channel call. To ensure the correct behavior for all types of channels, the
close_channel must be called before free_channel.
Diffstat (limited to 'src')
| -rw-r--r-- | src/nvim/msgpack_rpc/channel.c | 26 | 
1 files changed, 13 insertions, 13 deletions
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 94605c37e9..3622c8252d 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -225,6 +225,10 @@ Object channel_send_call(uint64_t id,      return NIL;    } +  if (channel->closed && !kv_size(channel->call_stack)) { +    free_channel(channel); +  } +    return frame.result;  } @@ -328,7 +332,7 @@ static void parse_msgpack(RStream *rstream, void *data, bool eof)    Channel *channel = data;    if (eof) { -    goto end; +    close_channel(channel);    }    size_t count = rstream_pending(rstream); @@ -363,7 +367,7 @@ static void parse_msgpack(RStream *rstream, void *data, bool eof)        }        msgpack_unpacked_destroy(&unpacked);        // Bail out from this event loop iteration -      goto end; +      return;      }      handle_request(channel, &unpacked.data); @@ -386,14 +390,6 @@ static void parse_msgpack(RStream *rstream, void *data, bool eof)                             "This error can also happen when deserializing "                             "an object with high level of nesting");    } - -end: -  if (eof && !channel->is_job && !kv_size(channel->call_stack)) { -    // The free_channel call is deferred for jobs because it's possible that -    // job_stderr will called after this. For non-job channels, this is the -    // last callback so it must be freed now. -    free_channel(channel); -  }  }  static void handle_request(Channel *channel, msgpack_object *request) @@ -569,6 +565,10 @@ static void unsubscribe(Channel *channel, char *event)  /// free_channel later.  static void close_channel(Channel *channel)  { +  if (channel->closed) { +    return; +  } +    channel->closed = true;    if (channel->is_job) {      if (channel->data.job) { @@ -577,10 +577,10 @@ static void close_channel(Channel *channel)    } else {      rstream_free(channel->data.streams.read);      wstream_free(channel->data.streams.write); -    if (channel->data.streams.uv) { -      uv_close((uv_handle_t *)channel->data.streams.uv, close_cb); +    uv_handle_t *handle = (uv_handle_t *)channel->data.streams.uv; +    if (handle) { +      uv_close(handle, close_cb);      } else { -      // When the stdin channel closes, it's time to go        mch_exit(0);      }    }  | 
