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;