@cryptotaxi247 / netdata-1 / commits / 0c06f38f6

Fix valgrind errors (#7532)

* Add callbacks to pipe handle destructors * Fix valgrind errors

Markos Fountoulakis committed Dec 15, 2019 at 20:56 UTC 0c06f38f6e9e687814e245b01f4b4f7af2314eda
1 file changed +38 -30
daemon/commands.c
+38 -30
@@ -18,16 +18,19 @@ char cmd_prefix_by_status[] = {
18 static int command_thread_error;
19 static int command_thread_shutdown;
20 static unsigned clients = 0;
21 -static char command_string[MAX_COMMAND_LENGTH];
22 -static unsigned command_string_size;
21
22 struct command_context {
23 + /* embedded client pipe structure at address 0 */
24 + uv_pipe_t client;
25 +
26 uv_work_t work;
26 - uv_stream_t *client;
27 + uv_write_t write_req;
28 cmd_t idx;
29 char *args;
30 char *message;
31 cmd_status_t status;
32 + char command_string[MAX_COMMAND_LENGTH];
33 + unsigned command_string_size;
34 };
35
36 /* Forward declarations */
@@ -219,13 +222,18 @@ static void cmd_unlock_high_priority(unsigned index)
222 (void)index;
223 }
224
225 +static void pipe_close_cb(uv_handle_t* handle)
226 +{
227 + /* Also frees command context */
228 + freez(handle);
229 +}
230 +
231 static void pipe_write_cb(uv_write_t* req, int status)
232 {
233 (void)status;
234 uv_pipe_t *client = req->data;
235
227 - uv_close((uv_handle_t *)client, NULL);
228 - freez(client);
236 + uv_close((uv_handle_t *)client, pipe_close_cb);
237 --clients;
238 info("Command Clients = %u\n", clients);
239 }
@@ -244,14 +252,14 @@ static inline void add_string_to_command_reply(char *reply_string, unsigned *rep
252 *reply_string_size += len;
253 }
254
247 -static void send_command_reply(uv_stream_t *client, cmd_status_t status, char *message)
255 +static void send_command_reply(struct command_context *cmd_ctx, cmd_status_t status, char *message)
256 {
257 int ret;
258 char reply_string[MAX_COMMAND_LENGTH] = {'\0', };
259 char exit_status_string[MAX_EXIT_STATUS_LENGTH + 1] = {'\0', };
260 unsigned reply_string_size = 0;
261 uv_buf_t write_buf;
254 - uv_write_t write_req;
262 + uv_stream_t *client = (uv_stream_t *)(uv_pipe_t *)cmd_ctx;
263
264 snprintfz(exit_status_string, MAX_EXIT_STATUS_LENGTH, "%u", status);
265 add_char_to_command_reply(reply_string, &reply_string_size, CMD_PREFIX_EXIT_CODE);
@@ -263,10 +271,10 @@ static void send_command_reply(uv_stream_t *client, cmd_status_t status, char *m
271 add_string_to_command_reply(reply_string, &reply_string_size, message);
272 }
273
266 - write_req.data = client;
274 + cmd_ctx->write_req.data = client;
275 write_buf.base = reply_string;
276 write_buf.len = reply_string_size;
269 - ret = uv_write(&write_req, (uv_stream_t *)client, &write_buf, 1, pipe_write_cb);
277 + ret = uv_write(&cmd_ctx->write_req, (uv_stream_t *)client, &write_buf, 1, pipe_write_cb);
278 if (ret) {
279 error("uv_write(): %s", uv_strerror(ret));
280 }
@@ -291,7 +299,7 @@ static void after_schedule_command(uv_work_t *req, int status)
299
300 (void)status;
301
294 - send_command_reply(cmd_ctx->client, cmd_ctx->status, cmd_ctx->message);
302 + send_command_reply(cmd_ctx, cmd_ctx->status, cmd_ctx->message);
303 if (cmd_ctx->message)
304 freez(cmd_ctx->message);
305 }
@@ -303,22 +311,19 @@ static void schedule_command(uv_work_t *req)
311 cmd_ctx->status = execute_command(cmd_ctx->idx, cmd_ctx->args, &cmd_ctx->message);
312 }
313
306 -static void parse_commands(uv_stream_t *client)
314 +static void parse_commands(struct command_context *cmd_ctx)
315 {
316 char *message = NULL, *pos;
317 cmd_t i;
318 cmd_status_t status;
311 - struct command_context *cmd_ctx;
319
320 status = CMD_STATUS_FAILURE;
321
322 /* Skip white-space characters */
316 - for (pos = command_string ; isspace(*pos) && ('\0' != *pos) ; ++pos) {;}
323 + for (pos = cmd_ctx->command_string ; isspace(*pos) && ('\0' != *pos) ; ++pos) {;}
324 for (i = 0 ; i < CMD_TOTAL_COMMANDS ; ++i) {
325 if (!strncmp(pos, command_info_array[i].cmd_str, strlen(command_info_array[i].cmd_str))) {
319 - cmd_ctx = mallocz(sizeof(*cmd_ctx));
326 cmd_ctx->work.data = cmd_ctx;
321 - cmd_ctx->client = client;
327 cmd_ctx->idx = i;
328 cmd_ctx->args = pos + strlen(command_info_array[i].cmd_str);
329 cmd_ctx->message = NULL;
@@ -330,18 +335,20 @@ static void parse_commands(uv_stream_t *client)
335 if (CMD_TOTAL_COMMANDS == i) {
336 /* no command found */
337 message = strdupz("Illegal command. Please type \"help\" for instructions.");
333 - send_command_reply(client, status, message);
338 + send_command_reply(cmd_ctx, status, message);
339 freez(message);
340 }
341 }
342
343 static void pipe_read_cb(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf)
344 {
345 + struct command_context *cmd_ctx = (struct command_context *)client;
346 +
347 if (0 == nread) {
348 info("%s: Zero bytes read by command pipe.", __func__);
349 } else if (UV_EOF == nread) {
350 info("EOF found in command pipe.");
344 - parse_commands(client);
351 + parse_commands(cmd_ctx);
352 } else if (nread < 0) {
353 error("%s: %s", __func__, uv_strerror(nread));
354 }
@@ -351,17 +358,17 @@ static void pipe_read_cb(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf
358 } else if (nread) {
359 size_t to_copy;
360
354 - to_copy = MIN(nread, MAX_COMMAND_LENGTH - 1 - command_string_size);
355 - strncpyz(command_string + command_string_size, buf->base, to_copy);
356 - command_string_size += to_copy;
361 + to_copy = MIN(nread, MAX_COMMAND_LENGTH - 1 - cmd_ctx->command_string_size);
362 + memcpy(cmd_ctx->command_string + cmd_ctx->command_string_size, buf->base, to_copy);
363 + cmd_ctx->command_string_size += to_copy;
364 + cmd_ctx->command_string[cmd_ctx->command_string_size] = '\0';
365 }
366 if (buf && buf->len) {
367 freez(buf->base);
368 }
369
370 if (nread < 0 && UV_EOF != nread) {
363 - uv_close((uv_handle_t *)client, NULL);
364 - freez(client);
371 + uv_close((uv_handle_t *)client, pipe_close_cb);
372 --clients;
373 info("Command Clients = %u\n", clients);
374 }
@@ -379,34 +386,35 @@ static void connection_cb(uv_stream_t *server, int status)
386 {
387 int ret;
388 uv_pipe_t *client;
389 + struct command_context *cmd_ctx;
390 assert(status == 0);
391
384 - client = mallocz(sizeof(*client));
392 + /* combined allocation of client pipe and command context */
393 + cmd_ctx = mallocz(sizeof(*cmd_ctx));
394 + client = (uv_pipe_t *)cmd_ctx;
395 ret = uv_pipe_init(server->loop, client, 1);
396 if (ret) {
397 error("uv_pipe_init(): %s", uv_strerror(ret));
388 - freez(client);
398 + freez(cmd_ctx);
399 return;
400 }
401 ret = uv_accept(server, (uv_stream_t *)client);
402 if (ret) {
403 error("uv_accept(): %s", uv_strerror(ret));
394 - uv_close((uv_handle_t *)client, NULL);
395 - freez(client);
404 + uv_close((uv_handle_t *)client, pipe_close_cb);
405 return;
406 }
407
408 ++clients;
409 info("Command Clients = %u\n", clients);
410 /* Start parsing a new command */
402 - command_string_size = 0;
403 - command_string[0] = '\0';
411 + cmd_ctx->command_string_size = 0;
412 + cmd_ctx->command_string[0] = '\0';
413
414 ret = uv_read_start((uv_stream_t*)client, alloc_cb, pipe_read_cb);
415 if (ret) {
416 error("uv_read_start(): %s", uv_strerror(ret));
408 - uv_close((uv_handle_t *)client, NULL);
409 - freez(client);
417 + uv_close((uv_handle_t *)client, pipe_close_cb);
418 --clients;
419 info("Command Clients = %u\n", clients);
420 return;