From c2f3e361c52ec4e7149ea1d8c6a1202e0873da8e Mon Sep 17 00:00:00 2001 From: ZyX Date: Wed, 19 Apr 2017 19:11:50 +0300 Subject: *: Add comment to all C files --- src/nvim/msgpack_rpc/channel.c | 3 +++ src/nvim/msgpack_rpc/helpers.c | 3 +++ src/nvim/msgpack_rpc/server.c | 3 +++ 3 files changed, 9 insertions(+) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 259dcc523c..b2c6ef852c 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include #include #include diff --git a/src/nvim/msgpack_rpc/helpers.c b/src/nvim/msgpack_rpc/helpers.c index 4d8a9984e1..967ce31c1b 100644 --- a/src/nvim/msgpack_rpc/helpers.c +++ b/src/nvim/msgpack_rpc/helpers.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include #include #include diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c index d7c2926a0f..b6958088ca 100644 --- a/src/nvim/msgpack_rpc/server.c +++ b/src/nvim/msgpack_rpc/server.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include #include #include -- cgit From 5c9860a0a2bf27d409c986673f0a74542561c4c3 Mon Sep 17 00:00:00 2001 From: Sander Bosma Date: Wed, 1 Mar 2017 10:43:47 +0100 Subject: api: Do not truncate errors <1 MB. #6237 Closes #5984 --- src/nvim/msgpack_rpc/channel.c | 73 +++++++++++++++++++++--------------------- src/nvim/msgpack_rpc/helpers.c | 22 ++++++------- 2 files changed, 47 insertions(+), 48 deletions(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index b2c6ef852c..06cdf7d1f1 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -192,7 +192,7 @@ Object channel_send_call(uint64_t id, Channel *channel = NULL; if (!(channel = pmap_get(uint64_t)(channels, id)) || channel->closed) { - api_set_error(err, Exception, _("Invalid channel \"%" PRIu64 "\""), id); + _api_set_error(err, kErrorTypeException, _("Invalid channel \"%" PRIu64 "\""), id); api_free_array(args); return NIL; } @@ -212,7 +212,7 @@ Object channel_send_call(uint64_t id, if (frame.errored) { if (frame.result.type == kObjectTypeString) { - api_set_error(err, Exception, "%s", frame.result.data.string.data); + _api_set_error(err, kErrorTypeException, "%s", frame.result.data.string.data); } else if (frame.result.type == kObjectTypeArray) { // Should be an error in the form [type, message] Array array = frame.result.data.array; @@ -220,14 +220,13 @@ Object channel_send_call(uint64_t id, && (array.items[0].data.integer == kErrorTypeException || array.items[0].data.integer == kErrorTypeValidation) && array.items[1].type == kObjectTypeString) { - err->type = (ErrorType) array.items[0].data.integer; - xstrlcpy(err->msg, array.items[1].data.string.data, sizeof(err->msg)); - err->set = true; + _api_set_error(err, (ErrorType)array.items[0].data.integer, "%s", + array.items[1].data.string.data); } else { - api_set_error(err, Exception, "%s", "unknown error"); + _api_set_error(err, kErrorTypeException, "%s", "unknown error"); } } else { - api_set_error(err, Exception, "%s", "unknown error"); + _api_set_error(err, kErrorTypeException, "%s", "unknown error"); } api_free_object(frame.result); @@ -412,38 +411,38 @@ static void handle_request(Channel *channel, msgpack_object *request) channel->id); call_set_error(channel, buf); } - return; - } - - // Retrieve the request handler - MsgpackRpcRequestHandler handler; - msgpack_object *method = msgpack_rpc_method(request); - - if (method) { - handler = msgpack_rpc_get_handler_for(method->via.bin.ptr, - method->via.bin.size); } else { - handler.fn = msgpack_rpc_handle_missing_method; - handler.async = true; - } + // Retrieve the request handler + MsgpackRpcRequestHandler handler; + msgpack_object *method = msgpack_rpc_method(request); - Array args = ARRAY_DICT_INIT; - if (!msgpack_rpc_to_array(msgpack_rpc_args(request), &args)) { - handler.fn = msgpack_rpc_handle_invalid_arguments; - handler.async = true; - } + if (method) { + handler = msgpack_rpc_get_handler_for(method->via.bin.ptr, + method->via.bin.size); + } else { + handler.fn = msgpack_rpc_handle_missing_method; + handler.async = true; + } - RequestEvent *event_data = xmalloc(sizeof(RequestEvent)); - event_data->channel = channel; - event_data->handler = handler; - event_data->args = args; - event_data->request_id = request_id; - incref(channel); - if (handler.async) { - on_request_event((void **)&event_data); - } else { - multiqueue_put(channel->events, on_request_event, 1, event_data); + Array args = ARRAY_DICT_INIT; + if (!msgpack_rpc_to_array(msgpack_rpc_args(request), &args)) { + handler.fn = msgpack_rpc_handle_invalid_arguments; + handler.async = true; + } + + RequestEvent *event_data = xmalloc(sizeof(RequestEvent)); + event_data->channel = channel; + event_data->handler = handler; + event_data->args = args; + event_data->request_id = request_id; + incref(channel); + if (handler.async) { + on_request_event((void **)&event_data); + } else { + multiqueue_put(channel->events, on_request_event, 1, event_data); + } } + xfree(error.msg); } static void on_request_event(void **argv) @@ -470,6 +469,7 @@ static void on_request_event(void **argv) api_free_array(args); decref(channel); xfree(e); + xfree(error.msg); } static bool channel_write(Channel *channel, WBuffer *buffer) @@ -512,12 +512,13 @@ static bool channel_write(Channel *channel, WBuffer *buffer) static void send_error(Channel *channel, uint64_t id, char *err) { Error e = ERROR_INIT; - api_set_error(&e, Exception, "%s", err); + _api_set_error(&e, kErrorTypeException, "%s", err); channel_write(channel, serialize_response(channel->id, id, &e, NIL, &out_buffer)); + xfree(e.msg); } static void send_request(Channel *channel, diff --git a/src/nvim/msgpack_rpc/helpers.c b/src/nvim/msgpack_rpc/helpers.c index 967ce31c1b..c273343b41 100644 --- a/src/nvim/msgpack_rpc/helpers.c +++ b/src/nvim/msgpack_rpc/helpers.c @@ -475,8 +475,7 @@ Object msgpack_rpc_handle_missing_method(uint64_t channel_id, Array args, Error *error) { - snprintf(error->msg, sizeof(error->msg), "Invalid method name"); - error->set = true; + _api_set_error(error, error->type, "Invalid method name"); return NIL; } @@ -485,8 +484,7 @@ Object msgpack_rpc_handle_invalid_arguments(uint64_t channel_id, Array args, Error *error) { - snprintf(error->msg, sizeof(error->msg), "Invalid method arguments"); - error->set = true; + _api_set_error(error, error->type, "Invalid method arguments"); return NIL; } @@ -572,29 +570,29 @@ void msgpack_rpc_validate(uint64_t *response_id, *response_id = NO_RESPONSE; // Validate the basic structure of the msgpack-rpc payload if (req->type != MSGPACK_OBJECT_ARRAY) { - api_set_error(err, Validation, _("Message is not an array")); + _api_set_error(err, kErrorTypeValidation, _("Message is not an array")); return; } if (req->via.array.size == 0) { - api_set_error(err, Validation, _("Message is empty")); + _api_set_error(err, kErrorTypeValidation, _("Message is empty")); return; } if (req->via.array.ptr[0].type != MSGPACK_OBJECT_POSITIVE_INTEGER) { - api_set_error(err, Validation, _("Message type must be an integer")); + _api_set_error(err, kErrorTypeValidation, _("Message type must be an integer")); return; } uint64_t type = req->via.array.ptr[0].via.u64; if (type != kMessageTypeRequest && type != kMessageTypeNotification) { - api_set_error(err, Validation, _("Unknown message type")); + _api_set_error(err, kErrorTypeValidation, _("Unknown message type")); return; } if ((type == kMessageTypeRequest && req->via.array.size != 4) || (type == kMessageTypeNotification && req->via.array.size != 3)) { - api_set_error(err, Validation, _("Request array size should be 4 (request) " + _api_set_error(err, kErrorTypeValidation, _("Request array size should be 4 (request) " "or 3 (notification)")); return; } @@ -602,19 +600,19 @@ void msgpack_rpc_validate(uint64_t *response_id, if (type == kMessageTypeRequest) { msgpack_object *id_obj = msgpack_rpc_msg_id(req); if (!id_obj) { - api_set_error(err, Validation, _("ID must be a positive integer")); + _api_set_error(err, kErrorTypeValidation, _("ID must be a positive integer")); return; } *response_id = id_obj->via.u64; } if (!msgpack_rpc_method(req)) { - api_set_error(err, Validation, _("Method must be a string")); + _api_set_error(err, kErrorTypeValidation, _("Method must be a string")); return; } if (!msgpack_rpc_args(req)) { - api_set_error(err, Validation, _("Parameters must be an array")); + _api_set_error(err, kErrorTypeValidation, _("Parameters must be an array")); return; } } -- cgit From 2a49163103827465f25810f5f4e3d4305159f209 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 23 Apr 2017 15:59:59 +0200 Subject: api_clear_error() --- src/nvim/msgpack_rpc/channel.c | 60 +++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 30 deletions(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 06cdf7d1f1..bd7f84fed9 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -411,38 +411,38 @@ static void handle_request(Channel *channel, msgpack_object *request) channel->id); call_set_error(channel, buf); } - } else { - // Retrieve the request handler - MsgpackRpcRequestHandler handler; - msgpack_object *method = msgpack_rpc_method(request); + api_clear_error(&error); + return; + } + // Retrieve the request handler + MsgpackRpcRequestHandler handler; + msgpack_object *method = msgpack_rpc_method(request); - if (method) { - handler = msgpack_rpc_get_handler_for(method->via.bin.ptr, - method->via.bin.size); - } else { - handler.fn = msgpack_rpc_handle_missing_method; - handler.async = true; - } + if (method) { + handler = msgpack_rpc_get_handler_for(method->via.bin.ptr, + method->via.bin.size); + } else { + handler.fn = msgpack_rpc_handle_missing_method; + handler.async = true; + } - Array args = ARRAY_DICT_INIT; - if (!msgpack_rpc_to_array(msgpack_rpc_args(request), &args)) { - handler.fn = msgpack_rpc_handle_invalid_arguments; - handler.async = true; - } + Array args = ARRAY_DICT_INIT; + if (!msgpack_rpc_to_array(msgpack_rpc_args(request), &args)) { + handler.fn = msgpack_rpc_handle_invalid_arguments; + handler.async = true; + } - RequestEvent *event_data = xmalloc(sizeof(RequestEvent)); - event_data->channel = channel; - event_data->handler = handler; - event_data->args = args; - event_data->request_id = request_id; - incref(channel); - if (handler.async) { - on_request_event((void **)&event_data); - } else { - multiqueue_put(channel->events, on_request_event, 1, event_data); - } + RequestEvent *event_data = xmalloc(sizeof(RequestEvent)); + event_data->channel = channel; + event_data->handler = handler; + event_data->args = args; + event_data->request_id = request_id; + incref(channel); + if (handler.async) { + on_request_event((void **)&event_data); + } else { + multiqueue_put(channel->events, on_request_event, 1, event_data); } - xfree(error.msg); } static void on_request_event(void **argv) @@ -469,7 +469,7 @@ static void on_request_event(void **argv) api_free_array(args); decref(channel); xfree(e); - xfree(error.msg); + api_clear_error(&error); } static bool channel_write(Channel *channel, WBuffer *buffer) @@ -518,7 +518,7 @@ static void send_error(Channel *channel, uint64_t id, char *err) &e, NIL, &out_buffer)); - xfree(e.msg); + api_clear_error(&e); } static void send_request(Channel *channel, -- cgit From 2ed91f222f1dddda10fbdc9cb80df2be7d4c2da3 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 23 Apr 2017 19:58:13 +0200 Subject: api/internal: Remove `set` field from Error type. --- src/nvim/msgpack_rpc/channel.c | 2 +- src/nvim/msgpack_rpc/helpers.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index bd7f84fed9..36a3210c70 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -397,7 +397,7 @@ static void handle_request(Channel *channel, msgpack_object *request) Error error = ERROR_INIT; msgpack_rpc_validate(&request_id, request, &error); - if (error.set) { + if (ERROR_SET(&error)) { // Validation failed, send response with error if (channel_write(channel, serialize_response(channel->id, diff --git a/src/nvim/msgpack_rpc/helpers.c b/src/nvim/msgpack_rpc/helpers.c index c273343b41..800f5edb85 100644 --- a/src/nvim/msgpack_rpc/helpers.c +++ b/src/nvim/msgpack_rpc/helpers.c @@ -475,7 +475,7 @@ Object msgpack_rpc_handle_missing_method(uint64_t channel_id, Array args, Error *error) { - _api_set_error(error, error->type, "Invalid method name"); + _api_set_error(error, kErrorTypeException, "Invalid method name"); return NIL; } @@ -484,7 +484,7 @@ Object msgpack_rpc_handle_invalid_arguments(uint64_t channel_id, Array args, Error *error) { - _api_set_error(error, error->type, "Invalid method arguments"); + _api_set_error(error, kErrorTypeException, "Invalid method arguments"); return NIL; } @@ -517,7 +517,7 @@ void msgpack_rpc_serialize_response(uint64_t response_id, msgpack_pack_int(pac, 1); msgpack_pack_uint64(pac, response_id); - if (err->set) { + if (ERROR_SET(err)) { // error represented by a [type, message] array msgpack_pack_array(pac, 2); msgpack_rpc_from_integer(err->type, pac); -- cgit From 3fbc660d57f4726044662bde1bf52c527e45fb98 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 23 Apr 2017 21:54:44 +0200 Subject: api_set_error(): rename --- src/nvim/msgpack_rpc/channel.c | 12 ++++++------ src/nvim/msgpack_rpc/helpers.c | 20 ++++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 36a3210c70..3cf85316d9 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -192,7 +192,7 @@ Object channel_send_call(uint64_t id, Channel *channel = NULL; if (!(channel = pmap_get(uint64_t)(channels, id)) || channel->closed) { - _api_set_error(err, kErrorTypeException, _("Invalid channel \"%" PRIu64 "\""), id); + api_set_error(err, kErrorTypeException, _("Invalid channel \"%" PRIu64 "\""), id); api_free_array(args); return NIL; } @@ -212,7 +212,7 @@ Object channel_send_call(uint64_t id, if (frame.errored) { if (frame.result.type == kObjectTypeString) { - _api_set_error(err, kErrorTypeException, "%s", frame.result.data.string.data); + api_set_error(err, kErrorTypeException, "%s", frame.result.data.string.data); } else if (frame.result.type == kObjectTypeArray) { // Should be an error in the form [type, message] Array array = frame.result.data.array; @@ -220,13 +220,13 @@ Object channel_send_call(uint64_t id, && (array.items[0].data.integer == kErrorTypeException || array.items[0].data.integer == kErrorTypeValidation) && array.items[1].type == kObjectTypeString) { - _api_set_error(err, (ErrorType)array.items[0].data.integer, "%s", + api_set_error(err, (ErrorType)array.items[0].data.integer, "%s", array.items[1].data.string.data); } else { - _api_set_error(err, kErrorTypeException, "%s", "unknown error"); + api_set_error(err, kErrorTypeException, "%s", "unknown error"); } } else { - _api_set_error(err, kErrorTypeException, "%s", "unknown error"); + api_set_error(err, kErrorTypeException, "%s", "unknown error"); } api_free_object(frame.result); @@ -512,7 +512,7 @@ static bool channel_write(Channel *channel, WBuffer *buffer) static void send_error(Channel *channel, uint64_t id, char *err) { Error e = ERROR_INIT; - _api_set_error(&e, kErrorTypeException, "%s", err); + api_set_error(&e, kErrorTypeException, "%s", err); channel_write(channel, serialize_response(channel->id, id, &e, diff --git a/src/nvim/msgpack_rpc/helpers.c b/src/nvim/msgpack_rpc/helpers.c index 800f5edb85..0ad1d9ae4b 100644 --- a/src/nvim/msgpack_rpc/helpers.c +++ b/src/nvim/msgpack_rpc/helpers.c @@ -475,7 +475,7 @@ Object msgpack_rpc_handle_missing_method(uint64_t channel_id, Array args, Error *error) { - _api_set_error(error, kErrorTypeException, "Invalid method name"); + api_set_error(error, kErrorTypeException, "Invalid method name"); return NIL; } @@ -484,7 +484,7 @@ Object msgpack_rpc_handle_invalid_arguments(uint64_t channel_id, Array args, Error *error) { - _api_set_error(error, kErrorTypeException, "Invalid method arguments"); + api_set_error(error, kErrorTypeException, "Invalid method arguments"); return NIL; } @@ -570,29 +570,29 @@ void msgpack_rpc_validate(uint64_t *response_id, *response_id = NO_RESPONSE; // Validate the basic structure of the msgpack-rpc payload if (req->type != MSGPACK_OBJECT_ARRAY) { - _api_set_error(err, kErrorTypeValidation, _("Message is not an array")); + api_set_error(err, kErrorTypeValidation, _("Message is not an array")); return; } if (req->via.array.size == 0) { - _api_set_error(err, kErrorTypeValidation, _("Message is empty")); + api_set_error(err, kErrorTypeValidation, _("Message is empty")); return; } if (req->via.array.ptr[0].type != MSGPACK_OBJECT_POSITIVE_INTEGER) { - _api_set_error(err, kErrorTypeValidation, _("Message type must be an integer")); + api_set_error(err, kErrorTypeValidation, _("Message type must be an integer")); return; } uint64_t type = req->via.array.ptr[0].via.u64; if (type != kMessageTypeRequest && type != kMessageTypeNotification) { - _api_set_error(err, kErrorTypeValidation, _("Unknown message type")); + api_set_error(err, kErrorTypeValidation, _("Unknown message type")); return; } if ((type == kMessageTypeRequest && req->via.array.size != 4) || (type == kMessageTypeNotification && req->via.array.size != 3)) { - _api_set_error(err, kErrorTypeValidation, _("Request array size should be 4 (request) " + api_set_error(err, kErrorTypeValidation, _("Request array size should be 4 (request) " "or 3 (notification)")); return; } @@ -600,19 +600,19 @@ void msgpack_rpc_validate(uint64_t *response_id, if (type == kMessageTypeRequest) { msgpack_object *id_obj = msgpack_rpc_msg_id(req); if (!id_obj) { - _api_set_error(err, kErrorTypeValidation, _("ID must be a positive integer")); + api_set_error(err, kErrorTypeValidation, _("ID must be a positive integer")); return; } *response_id = id_obj->via.u64; } if (!msgpack_rpc_method(req)) { - _api_set_error(err, kErrorTypeValidation, _("Method must be a string")); + api_set_error(err, kErrorTypeValidation, _("Method must be a string")); return; } if (!msgpack_rpc_args(req)) { - _api_set_error(err, kErrorTypeValidation, _("Parameters must be an array")); + api_set_error(err, kErrorTypeValidation, _("Parameters must be an array")); return; } } -- cgit From 086c354a0aad2769042dc91bf5bad021109f56e4 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 23 Apr 2017 22:30:08 +0200 Subject: api: Do not translate error messages. Also re-word some error messages: - "Key does not exist: %s" - "Invalid channel: %" - "Request array size must be 4 (request) or 3 (notification)" - "String cannot contain newlines" References #6150 --- src/nvim/msgpack_rpc/channel.c | 7 ++++--- src/nvim/msgpack_rpc/helpers.c | 18 +++++++++--------- 2 files changed, 13 insertions(+), 12 deletions(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 3cf85316d9..59594357de 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -192,7 +192,7 @@ Object channel_send_call(uint64_t id, Channel *channel = NULL; if (!(channel = pmap_get(uint64_t)(channels, id)) || channel->closed) { - api_set_error(err, kErrorTypeException, _("Invalid channel \"%" PRIu64 "\""), id); + api_set_error(err, kErrorTypeException, "Invalid channel: %" PRIu64, id); api_free_array(args); return NIL; } @@ -212,7 +212,8 @@ Object channel_send_call(uint64_t id, if (frame.errored) { if (frame.result.type == kObjectTypeString) { - api_set_error(err, kErrorTypeException, "%s", frame.result.data.string.data); + api_set_error(err, kErrorTypeException, "%s", + frame.result.data.string.data); } else if (frame.result.type == kObjectTypeArray) { // Should be an error in the form [type, message] Array array = frame.result.data.array; @@ -221,7 +222,7 @@ Object channel_send_call(uint64_t id, || array.items[0].data.integer == kErrorTypeValidation) && array.items[1].type == kObjectTypeString) { api_set_error(err, (ErrorType)array.items[0].data.integer, "%s", - array.items[1].data.string.data); + array.items[1].data.string.data); } else { api_set_error(err, kErrorTypeException, "%s", "unknown error"); } diff --git a/src/nvim/msgpack_rpc/helpers.c b/src/nvim/msgpack_rpc/helpers.c index 0ad1d9ae4b..0228582d37 100644 --- a/src/nvim/msgpack_rpc/helpers.c +++ b/src/nvim/msgpack_rpc/helpers.c @@ -570,49 +570,49 @@ void msgpack_rpc_validate(uint64_t *response_id, *response_id = NO_RESPONSE; // Validate the basic structure of the msgpack-rpc payload if (req->type != MSGPACK_OBJECT_ARRAY) { - api_set_error(err, kErrorTypeValidation, _("Message is not an array")); + api_set_error(err, kErrorTypeValidation, "Message is not an array"); return; } if (req->via.array.size == 0) { - api_set_error(err, kErrorTypeValidation, _("Message is empty")); + api_set_error(err, kErrorTypeValidation, "Message is empty"); return; } if (req->via.array.ptr[0].type != MSGPACK_OBJECT_POSITIVE_INTEGER) { - api_set_error(err, kErrorTypeValidation, _("Message type must be an integer")); + api_set_error(err, kErrorTypeValidation, "Message type must be an integer"); return; } uint64_t type = req->via.array.ptr[0].via.u64; if (type != kMessageTypeRequest && type != kMessageTypeNotification) { - api_set_error(err, kErrorTypeValidation, _("Unknown message type")); + api_set_error(err, kErrorTypeValidation, "Unknown message type"); return; } if ((type == kMessageTypeRequest && req->via.array.size != 4) || (type == kMessageTypeNotification && req->via.array.size != 3)) { - api_set_error(err, kErrorTypeValidation, _("Request array size should be 4 (request) " - "or 3 (notification)")); + api_set_error(err, kErrorTypeValidation, + "Request array size must be 4 (request) or 3 (notification)"); return; } if (type == kMessageTypeRequest) { msgpack_object *id_obj = msgpack_rpc_msg_id(req); if (!id_obj) { - api_set_error(err, kErrorTypeValidation, _("ID must be a positive integer")); + api_set_error(err, kErrorTypeValidation, "ID must be a positive integer"); return; } *response_id = id_obj->via.u64; } if (!msgpack_rpc_method(req)) { - api_set_error(err, kErrorTypeValidation, _("Method must be a string")); + api_set_error(err, kErrorTypeValidation, "Method must be a string"); return; } if (!msgpack_rpc_args(req)) { - api_set_error(err, kErrorTypeValidation, _("Parameters must be an array")); + api_set_error(err, kErrorTypeValidation, "Parameters must be an array"); return; } } -- cgit From 3ea10077534cb1dcb1597ffcf85e601fa0c0e27b Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 13 Mar 2017 15:02:37 +0100 Subject: api: nvim_get_mode() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Asynchronous API functions are served immediately, which means pending input could change the state of Nvim shortly after an async API function result is returned. nvim_get_mode() is different: - If RPCs are known to be blocked, it responds immediately (without flushing the input/event queue) - else it is handled just-in-time before waiting for input, after pending input was processed. This makes the result more reliable (but not perfect). Internally this is handled as a special case, but _semantically_ nothing has changed: API users never know when input flushes, so this internal special-case doesn't violate that. As far as API users are concerned, nvim_get_mode() is just another asynchronous API function. In all cases nvim_get_mode() never blocks for more than the time it takes to flush the input/event queue (~µs). Note: This doesn't address #6166; nvim_get_mode() will provoke #6166 if e.g. `d` is operator-pending. Closes #6159 --- src/nvim/msgpack_rpc/channel.c | 10 ++++++++++ src/nvim/msgpack_rpc/helpers.c | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 59594357de..799e6eadef 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -28,7 +28,9 @@ #include "nvim/map.h" #include "nvim/log.h" #include "nvim/misc1.h" +#include "nvim/state.h" #include "nvim/lib/kvec.h" +#include "nvim/os/input.h" #define CHANNEL_BUFFER_SIZE 0xffff @@ -433,6 +435,14 @@ static void handle_request(Channel *channel, msgpack_object *request) handler.async = true; } + if (handler.async) { + char buf[256] = { 0 }; + memcpy(buf, method->via.bin.ptr, MIN(255, method->via.bin.size)); + if (strcmp("nvim_get_mode", buf) == 0) { + handler.async = input_blocking(); + } + } + RequestEvent *event_data = xmalloc(sizeof(RequestEvent)); event_data->channel = channel; event_data->handler = handler; diff --git a/src/nvim/msgpack_rpc/helpers.c b/src/nvim/msgpack_rpc/helpers.c index 0228582d37..91ef5524ea 100644 --- a/src/nvim/msgpack_rpc/helpers.c +++ b/src/nvim/msgpack_rpc/helpers.c @@ -76,7 +76,7 @@ typedef struct { size_t idx; } MPToAPIObjectStackItem; -/// Convert type used by msgpack parser to Neovim own API type +/// Convert type used by msgpack parser to Nvim API type. /// /// @param[in] obj Msgpack value to convert. /// @param[out] arg Location where result of conversion will be saved. -- cgit From acfd2a2a29ae852ecc965ca888eb5049400bf39d Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 14 Mar 2017 00:44:03 +0100 Subject: input.c: Process only safe events before blocking. Introduce multiqueue_process_priority() to process only events at or above a certain priority. --- src/nvim/msgpack_rpc/channel.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 799e6eadef..9e43924db1 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -435,24 +435,26 @@ static void handle_request(Channel *channel, msgpack_object *request) handler.async = true; } - if (handler.async) { - char buf[256] = { 0 }; - memcpy(buf, method->via.bin.ptr, MIN(255, method->via.bin.size)); - if (strcmp("nvim_get_mode", buf) == 0) { - handler.async = input_blocking(); - } - } - - RequestEvent *event_data = xmalloc(sizeof(RequestEvent)); - event_data->channel = channel; - event_data->handler = handler; - event_data->args = args; - event_data->request_id = request_id; + RequestEvent *evdata = xmalloc(sizeof(RequestEvent)); + evdata->channel = channel; + evdata->handler = handler; + evdata->args = args; + evdata->request_id = request_id; incref(channel); if (handler.async) { - on_request_event((void **)&event_data); + bool is_get_mode = sizeof("nvim_get_mode") - 1 == method->via.bin.size + && !strncmp("nvim_get_mode", method->via.bin.ptr, method->via.bin.size); + + if (is_get_mode && !input_blocking()) { + // Schedule on the main loop with special priority. #6247 + Event ev = event_create(kEvPriorityAsync, on_request_event, 1, evdata); + multiqueue_put_event(channel->events, ev); + } else { + // Invoke immediately. + on_request_event((void **)&evdata); + } } else { - multiqueue_put(channel->events, on_request_event, 1, event_data); + multiqueue_put(channel->events, on_request_event, 1, evdata); } } -- cgit From f17a8185191b778960953508a5bf9b5f95b0560c Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Thu, 27 Apr 2017 13:54:54 +0200 Subject: api/nvim_get_mode: Use child-queue instead of "priority". --- src/nvim/msgpack_rpc/channel.c | 7 +++---- src/nvim/msgpack_rpc/channel.h | 5 +++++ 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 9e43924db1..911f2a6fa4 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -28,7 +28,6 @@ #include "nvim/map.h" #include "nvim/log.h" #include "nvim/misc1.h" -#include "nvim/state.h" #include "nvim/lib/kvec.h" #include "nvim/os/input.h" @@ -91,6 +90,7 @@ static msgpack_sbuffer out_buffer; /// Initializes the module void channel_init(void) { + ch_before_blocking_events = multiqueue_new_child(main_loop.events); channels = pmap_new(uint64_t)(); event_strings = pmap_new(cstr_t)(); msgpack_sbuffer_init(&out_buffer); @@ -446,9 +446,8 @@ static void handle_request(Channel *channel, msgpack_object *request) && !strncmp("nvim_get_mode", method->via.bin.ptr, method->via.bin.size); if (is_get_mode && !input_blocking()) { - // Schedule on the main loop with special priority. #6247 - Event ev = event_create(kEvPriorityAsync, on_request_event, 1, evdata); - multiqueue_put_event(channel->events, ev); + // Defer the event to a special queue used by os/input.c. #6247 + multiqueue_put(ch_before_blocking_events, on_request_event, 1, evdata); } else { // Invoke immediately. on_request_event((void **)&evdata); diff --git a/src/nvim/msgpack_rpc/channel.h b/src/nvim/msgpack_rpc/channel.h index 0d92976d02..f8fe6f129b 100644 --- a/src/nvim/msgpack_rpc/channel.h +++ b/src/nvim/msgpack_rpc/channel.h @@ -11,6 +11,11 @@ #define METHOD_MAXLEN 512 +/// HACK: os/input.c drains this queue immediately before blocking for input. +/// Events on this queue are async-safe, but they need the resolved state +/// of os_inchar(), so they are processed "just-in-time". +MultiQueue *ch_before_blocking_events; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "msgpack_rpc/channel.h.generated.h" #endif -- cgit From 1483800cdff3bd00faabe66436a1618f567f6754 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 1 May 2017 17:04:56 +0200 Subject: coverity/161682: FP: Dereference after null check (#6630) --- src/nvim/msgpack_rpc/channel.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/nvim/msgpack_rpc') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 911f2a6fa4..cd64e14976 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -442,8 +442,7 @@ static void handle_request(Channel *channel, msgpack_object *request) evdata->request_id = request_id; incref(channel); if (handler.async) { - bool is_get_mode = sizeof("nvim_get_mode") - 1 == method->via.bin.size - && !strncmp("nvim_get_mode", method->via.bin.ptr, method->via.bin.size); + bool is_get_mode = handler.fn == handle_nvim_get_mode; if (is_get_mode && !input_blocking()) { // Defer the event to a special queue used by os/input.c. #6247 -- cgit