diff options
author | Drew DeVault <sir@cmpwn.com> | 2016-05-30 20:10:08 -0400 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2016-05-30 20:10:08 -0400 |
commit | 7f6b3d1c1f0727c8db623c18cc8a4fd948be995d (patch) | |
tree | bf308ff06cf9a5a8b6b0a82febaca3f5f5208e96 | |
parent | Update configuration info in readme (diff) | |
parent | sway: refactor ipc_client_handle_command() (diff) | |
download | sway-7f6b3d1c1f0727c8db623c18cc8a4fd948be995d.tar.gz sway-7f6b3d1c1f0727c8db623c18cc8a4fd948be995d.tar.zst sway-7f6b3d1c1f0727c8db623c18cc8a4fd948be995d.zip |
Merge pull request #637 from 1ace/fix/ipc-leak
Fix a few mem leaks in ipc-server
-rw-r--r-- | sway/ipc-server.c | 63 |
1 files changed, 36 insertions, 27 deletions
diff --git a/sway/ipc-server.c b/sway/ipc-server.c index a9325a81..13e1837a 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c | |||
@@ -138,6 +138,7 @@ int ipc_handle_connection(int fd, uint32_t mask, void *data) { | |||
138 | int flags; | 138 | int flags; |
139 | if ((flags=fcntl(client_fd, F_GETFD)) == -1 || fcntl(client_fd, F_SETFD, flags|FD_CLOEXEC) == -1) { | 139 | if ((flags=fcntl(client_fd, F_GETFD)) == -1 || fcntl(client_fd, F_SETFD, flags|FD_CLOEXEC) == -1) { |
140 | sway_log_errno(L_INFO, "Unable to set CLOEXEC on IPC client socket"); | 140 | sway_log_errno(L_INFO, "Unable to set CLOEXEC on IPC client socket"); |
141 | close(client_fd); | ||
141 | return 0; | 142 | return 0; |
142 | } | 143 | } |
143 | 144 | ||
@@ -291,6 +292,11 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
291 | } | 292 | } |
292 | 293 | ||
293 | char *buf = malloc(client->payload_length + 1); | 294 | char *buf = malloc(client->payload_length + 1); |
295 | if (!buf) { | ||
296 | sway_log_errno(L_INFO, "Out of memory"); | ||
297 | ipc_client_disconnect(client); | ||
298 | return; | ||
299 | } | ||
294 | if (client->payload_length > 0) | 300 | if (client->payload_length > 0) |
295 | { | 301 | { |
296 | ssize_t received = recv(client->fd, buf, client->payload_length, 0); | 302 | ssize_t received = recv(client->fd, buf, client->payload_length, 0); |
@@ -302,28 +308,27 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
302 | return; | 308 | return; |
303 | } | 309 | } |
304 | } | 310 | } |
311 | buf[client->payload_length] = '\0'; | ||
305 | 312 | ||
306 | switch (client->current_command) { | 313 | switch (client->current_command) { |
307 | case IPC_COMMAND: | 314 | case IPC_COMMAND: |
308 | { | 315 | { |
309 | buf[client->payload_length] = '\0'; | ||
310 | struct cmd_results *results = handle_command(buf); | 316 | struct cmd_results *results = handle_command(buf); |
311 | const char *json = cmd_results_to_json(results); | 317 | const char *json = cmd_results_to_json(results); |
312 | char reply[256]; | 318 | char reply[256]; |
313 | int length = snprintf(reply, sizeof(reply), "%s", json); | 319 | int length = snprintf(reply, sizeof(reply), "%s", json); |
314 | ipc_send_reply(client, reply, (uint32_t) length); | 320 | ipc_send_reply(client, reply, (uint32_t) length); |
315 | free_cmd_results(results); | 321 | free_cmd_results(results); |
316 | break; | 322 | goto exit_cleanup; |
317 | } | 323 | } |
324 | |||
318 | case IPC_SUBSCRIBE: | 325 | case IPC_SUBSCRIBE: |
319 | { | 326 | { |
320 | buf[client->payload_length] = '\0'; | ||
321 | struct json_object *request = json_tokener_parse(buf); | 327 | struct json_object *request = json_tokener_parse(buf); |
322 | if (request == NULL) { | 328 | if (request == NULL) { |
323 | ipc_send_reply(client, "{\"success\": false}", 18); | 329 | ipc_send_reply(client, "{\"success\": false}", 18); |
324 | ipc_client_disconnect(client); | 330 | sway_log_errno(L_INFO, "Failed to read request"); |
325 | free(buf); | 331 | goto exit_cleanup; |
326 | return; | ||
327 | } | 332 | } |
328 | 333 | ||
329 | // parse requested event types | 334 | // parse requested event types |
@@ -343,18 +348,18 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
343 | #endif | 348 | #endif |
344 | } else { | 349 | } else { |
345 | ipc_send_reply(client, "{\"success\": false}", 18); | 350 | ipc_send_reply(client, "{\"success\": false}", 18); |
346 | ipc_client_disconnect(client); | ||
347 | json_object_put(request); | 351 | json_object_put(request); |
348 | free(buf); | 352 | sway_log_errno(L_INFO, "Failed to parse request"); |
349 | return; | 353 | goto exit_cleanup; |
350 | } | 354 | } |
351 | } | 355 | } |
352 | 356 | ||
353 | json_object_put(request); | 357 | json_object_put(request); |
354 | 358 | ||
355 | ipc_send_reply(client, "{\"success\": true}", 17); | 359 | ipc_send_reply(client, "{\"success\": true}", 17); |
356 | break; | 360 | goto exit_cleanup; |
357 | } | 361 | } |
362 | |||
358 | case IPC_GET_WORKSPACES: | 363 | case IPC_GET_WORKSPACES: |
359 | { | 364 | { |
360 | json_object *workspaces = json_object_new_array(); | 365 | json_object *workspaces = json_object_new_array(); |
@@ -362,8 +367,9 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
362 | const char *json_string = json_object_to_json_string(workspaces); | 367 | const char *json_string = json_object_to_json_string(workspaces); |
363 | ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); | 368 | ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); |
364 | json_object_put(workspaces); // free | 369 | json_object_put(workspaces); // free |
365 | break; | 370 | goto exit_cleanup; |
366 | } | 371 | } |
372 | |||
367 | case IPC_GET_INPUTS: | 373 | case IPC_GET_INPUTS: |
368 | { | 374 | { |
369 | json_object *inputs = json_object_new_array(); | 375 | json_object *inputs = json_object_new_array(); |
@@ -380,8 +386,9 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
380 | const char *json_string = json_object_to_json_string(inputs); | 386 | const char *json_string = json_object_to_json_string(inputs); |
381 | ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); | 387 | ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); |
382 | json_object_put(inputs); | 388 | json_object_put(inputs); |
383 | break; | 389 | goto exit_cleanup; |
384 | } | 390 | } |
391 | |||
385 | case IPC_GET_OUTPUTS: | 392 | case IPC_GET_OUTPUTS: |
386 | { | 393 | { |
387 | json_object *outputs = json_object_new_array(); | 394 | json_object *outputs = json_object_new_array(); |
@@ -389,8 +396,9 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
389 | const char *json_string = json_object_to_json_string(outputs); | 396 | const char *json_string = json_object_to_json_string(outputs); |
390 | ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); | 397 | ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); |
391 | json_object_put(outputs); // free | 398 | json_object_put(outputs); // free |
392 | break; | 399 | goto exit_cleanup; |
393 | } | 400 | } |
401 | |||
394 | case IPC_GET_VERSION: | 402 | case IPC_GET_VERSION: |
395 | { | 403 | { |
396 | #if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE | 404 | #if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE |
@@ -418,29 +426,29 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
418 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); | 426 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); |
419 | json_object_put(json); // free | 427 | json_object_put(json); // free |
420 | free(full_version); | 428 | free(full_version); |
421 | break; | 429 | goto exit_cleanup; |
422 | } | 430 | } |
431 | |||
423 | case IPC_SWAY_GET_PIXELS: | 432 | case IPC_SWAY_GET_PIXELS: |
424 | { | 433 | { |
425 | char response_header[9]; | 434 | char response_header[9]; |
426 | memset(response_header, 0, sizeof(response_header)); | 435 | memset(response_header, 0, sizeof(response_header)); |
427 | buf[client->payload_length] = '\0'; | ||
428 | swayc_t *output = swayc_by_test(&root_container, output_by_name_test, buf); | 436 | swayc_t *output = swayc_by_test(&root_container, output_by_name_test, buf); |
429 | if (!output) { | 437 | if (!output) { |
430 | sway_log(L_ERROR, "IPC GET_PIXELS request with unknown output name"); | 438 | sway_log(L_ERROR, "IPC GET_PIXELS request with unknown output name"); |
431 | ipc_send_reply(client, response_header, sizeof(response_header)); | 439 | ipc_send_reply(client, response_header, sizeof(response_header)); |
432 | break; | 440 | goto exit_cleanup; |
433 | } | 441 | } |
434 | struct get_pixels_request *req = malloc(sizeof(struct get_pixels_request)); | 442 | struct get_pixels_request *req = malloc(sizeof(struct get_pixels_request)); |
435 | req->client = client; | 443 | req->client = client; |
436 | req->output = output->handle; | 444 | req->output = output->handle; |
437 | list_add(ipc_get_pixel_requests, req); | 445 | list_add(ipc_get_pixel_requests, req); |
438 | wlc_output_schedule_render(output->handle); | 446 | wlc_output_schedule_render(output->handle); |
439 | break; | 447 | goto exit_cleanup; |
440 | } | 448 | } |
449 | |||
441 | case IPC_GET_BAR_CONFIG: | 450 | case IPC_GET_BAR_CONFIG: |
442 | { | 451 | { |
443 | buf[client->payload_length] = '\0'; | ||
444 | if (!buf[0]) { | 452 | if (!buf[0]) { |
445 | // Send list of configured bar IDs | 453 | // Send list of configured bar IDs |
446 | json_object *bars = json_object_new_array(); | 454 | json_object *bars = json_object_new_array(); |
@@ -454,7 +462,6 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
454 | json_object_put(bars); // free | 462 | json_object_put(bars); // free |
455 | } else { | 463 | } else { |
456 | // Send particular bar's details | 464 | // Send particular bar's details |
457 | buf[client->payload_length] = '\0'; | ||
458 | struct bar_config *bar = NULL; | 465 | struct bar_config *bar = NULL; |
459 | int i; | 466 | int i; |
460 | for (i = 0; i < config->bars->length; ++i) { | 467 | for (i = 0; i < config->bars->length; ++i) { |
@@ -467,23 +474,24 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
467 | if (!bar) { | 474 | if (!bar) { |
468 | const char *error = "{ \"success\": false, \"error\": \"No bar with that ID\" }"; | 475 | const char *error = "{ \"success\": false, \"error\": \"No bar with that ID\" }"; |
469 | ipc_send_reply(client, error, (uint32_t)strlen(error)); | 476 | ipc_send_reply(client, error, (uint32_t)strlen(error)); |
470 | break; | 477 | goto exit_cleanup; |
471 | } | 478 | } |
472 | json_object *json = ipc_json_describe_bar_config(bar); | 479 | json_object *json = ipc_json_describe_bar_config(bar); |
473 | const char *json_string = json_object_to_json_string(json); | 480 | const char *json_string = json_object_to_json_string(json); |
474 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); | 481 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); |
475 | json_object_put(json); // free | 482 | json_object_put(json); // free |
476 | break; | ||
477 | } | 483 | } |
484 | goto exit_cleanup; | ||
478 | } | 485 | } |
486 | |||
479 | default: | 487 | default: |
480 | sway_log(L_INFO, "Unknown IPC command type %i", client->current_command); | 488 | sway_log(L_INFO, "Unknown IPC command type %i", client->current_command); |
481 | ipc_client_disconnect(client); | 489 | goto exit_cleanup; |
482 | return; | ||
483 | } | 490 | } |
484 | 491 | ||
485 | client->payload_length = 0; | 492 | exit_cleanup: |
486 | free(buf); | 493 | free(buf); |
494 | return; | ||
487 | } | 495 | } |
488 | 496 | ||
489 | bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length) { | 497 | bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length) { |
@@ -498,13 +506,11 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay | |||
498 | 506 | ||
499 | if (write(client->fd, data, ipc_header_size) == -1) { | 507 | if (write(client->fd, data, ipc_header_size) == -1) { |
500 | sway_log_errno(L_INFO, "Unable to send header to IPC client"); | 508 | sway_log_errno(L_INFO, "Unable to send header to IPC client"); |
501 | ipc_client_disconnect(client); | ||
502 | return false; | 509 | return false; |
503 | } | 510 | } |
504 | 511 | ||
505 | if (write(client->fd, payload, payload_length) == -1) { | 512 | if (write(client->fd, payload, payload_length) == -1) { |
506 | sway_log_errno(L_INFO, "Unable to send payload to IPC client"); | 513 | sway_log_errno(L_INFO, "Unable to send payload to IPC client"); |
507 | ipc_client_disconnect(client); | ||
508 | return false; | 514 | return false; |
509 | } | 515 | } |
510 | 516 | ||
@@ -653,7 +659,10 @@ void ipc_send_event(const char *json_string, enum ipc_command_type event) { | |||
653 | continue; | 659 | continue; |
654 | } | 660 | } |
655 | client->current_command = event; | 661 | client->current_command = event; |
656 | ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); | 662 | if (!ipc_send_reply(client, json_string, (uint32_t) strlen(json_string))) { |
663 | sway_log_errno(L_INFO, "Unable to send reply to IPC client"); | ||
664 | ipc_client_disconnect(client); | ||
665 | } | ||
657 | } | 666 | } |
658 | } | 667 | } |
659 | 668 | ||