diff options
| author | Thiago de Arruda <tpadilha84@gmail.com> | 2014-06-26 15:45:32 -0300 | 
|---|---|---|
| committer | Thiago de Arruda <tpadilha84@gmail.com> | 2014-07-17 11:30:01 -0300 | 
| commit | 0b2b1da0e809e529a25530d80a77284d618390cf (patch) | |
| tree | a510da2af871ca613eab81f5e48221671893fb35 /src | |
| parent | bce4c365bcd45eab76da967fd72732b79bbc1f57 (diff) | |
| download | rneovim-0b2b1da0e809e529a25530d80a77284d618390cf.tar.gz rneovim-0b2b1da0e809e529a25530d80a77284d618390cf.tar.bz2 rneovim-0b2b1da0e809e529a25530d80a77284d618390cf.zip  | |
channel: Bugfixes and refactor
- All functions that require a channel id will fail when the channel was
  disabled
- Rewrite `call_stack_unwind` as `call_set_error`. It will now disable the
  channel and set error on all frames. The stack will be unwinded automatically
  while the involved functions exit.
- Remove `disable_channel` function. If channels are disabled, they will be
  closed as soon as possible
Diffstat (limited to 'src')
| -rw-r--r-- | src/nvim/os/channel.c | 54 | 
1 files changed, 22 insertions, 32 deletions
diff --git a/src/nvim/os/channel.c b/src/nvim/os/channel.c index 439487f30b..efe628098c 100644 --- a/src/nvim/os/channel.c +++ b/src/nvim/os/channel.c @@ -143,7 +143,7 @@ bool channel_send_event(uint64_t id, char *name, Object arg)    Channel *channel = NULL;    if (id > 0) { -    if (!(channel = pmap_get(uint64_t)(channels, id))) { +    if (!(channel = pmap_get(uint64_t)(channels, id)) || !channel->enabled) {        msgpack_rpc_free_object(arg);        return false;      } @@ -163,7 +163,7 @@ bool channel_send_call(uint64_t id,  {    Channel *channel = NULL; -  if (!(channel = pmap_get(uint64_t)(channels, id))) { +  if (!(channel = pmap_get(uint64_t)(channels, id)) || !channel->enabled) {      msgpack_rpc_free_object(arg);      return false;    } @@ -178,6 +178,8 @@ bool channel_send_call(uint64_t id,          "while processing a RPC call",          channel->id);      *result = STRING_OBJ(cstr_to_string(buf)); +    msgpack_rpc_free_object(arg); +    return false;    }    uint64_t request_id = channel->next_request_id++; @@ -235,7 +237,7 @@ void channel_subscribe(uint64_t id, char *event)  {    Channel *channel; -  if (!(channel = pmap_get(uint64_t)(channels, id))) { +  if (!(channel = pmap_get(uint64_t)(channels, id)) || !channel->enabled) {      abort();    } @@ -257,7 +259,7 @@ void channel_unsubscribe(uint64_t id, char *event)  {    Channel *channel; -  if (!(channel = pmap_get(uint64_t)(channels, id))) { +  if (!(channel = pmap_get(uint64_t)(channels, id)) || !channel->enabled) {      abort();    } @@ -286,7 +288,7 @@ static void parse_msgpack(RStream *rstream, void *data, bool eof)               "Before returning from a RPC call, channel %" PRIu64 " was "               "closed by the client",               channel->id); -    disable_channel(channel, buf); +    call_set_error(channel, buf);      return;    } @@ -316,7 +318,7 @@ static void parse_msgpack(RStream *rstream, void *data, bool eof)                   " a matching id for the current RPC call. Ensure the client "                   " is properly synchronized",                   channel->id); -        call_stack_unwind(channel, buf, 1); +        call_set_error(channel, buf);        }        msgpack_unpacked_destroy(&unpacked);        // Bail out from this event loop iteration @@ -369,7 +371,7 @@ static bool channel_write(Channel *channel, WBuffer *buffer)               "Before returning from a RPC call, channel %" PRIu64 " was "               "closed due to a failed write",               channel->id); -    disable_channel(channel, buf); +    call_set_error(channel, buf);    }    return success; @@ -450,6 +452,15 @@ static void close_channel(Channel *channel)    pmap_del(uint64_t)(channels, channel->id);    msgpack_unpacker_free(channel->unpacker); +  // Unsubscribe from all events +  char *event_string; +  map_foreach_value(channel->subscribed_events, event_string, { +    unsubscribe(channel, event_string); +  }); + +  pmap_free(cstr_t)(channel->subscribed_events); +  kv_destroy(channel->call_stack); +    if (channel->is_job) {      if (channel->data.job) {        job_stop(channel->data.job); @@ -460,14 +471,6 @@ static void close_channel(Channel *channel)      uv_close((uv_handle_t *)channel->data.streams.uv, close_cb);    } -  // Unsubscribe from all events -  char *event_string; -  map_foreach_value(channel->subscribed_events, event_string, { -    unsubscribe(channel, event_string); -  }); - -  pmap_free(cstr_t)(channel->subscribed_events); -  kv_destroy(channel->call_stack);    free(channel);  } @@ -510,10 +513,8 @@ static bool is_valid_rpc_response(msgpack_object *obj, Channel *channel)  static void call_stack_pop(msgpack_object *obj, Channel *channel)  { -  ChannelCallFrame *frame = kv_A(channel->call_stack, -                                 kv_size(channel->call_stack) - 1); +  ChannelCallFrame *frame = kv_pop(channel->call_stack);    frame->errored = obj->via.array.ptr[2].type != MSGPACK_OBJECT_NIL; -  (void)kv_pop(channel->call_stack);    if (frame->errored) {      msgpack_rpc_to_object(&obj->via.array.ptr[2], &frame->result); @@ -522,24 +523,13 @@ static void call_stack_pop(msgpack_object *obj, Channel *channel)    }  } -static void call_stack_unwind(Channel *channel, char *msg, int count) +static void call_set_error(Channel *channel, char *msg)  { -  while (kv_size(channel->call_stack) && count--) { +  for (size_t i = 0; i < kv_size(channel->call_stack); i++) {      ChannelCallFrame *frame = kv_pop(channel->call_stack);      frame->errored = true;      frame->result = STRING_OBJ(cstr_to_string(msg));    } -} -static void disable_channel(Channel *channel, char *msg) -{ -  if (kv_size(channel->call_stack)) { -    // Channel is currently in the middle of a call, remove all frames and mark -    // it as "dead" -    channel->enabled = false; -    call_stack_unwind(channel, msg, -1); -  } else { -    // Safe to close it now -    close_channel(channel); -  } +  channel->enabled = false;  }  | 
