aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2016-05-30 20:10:08 -0400
committerLibravatar Drew DeVault <sir@cmpwn.com>2016-05-30 20:10:08 -0400
commit7f6b3d1c1f0727c8db623c18cc8a4fd948be995d (patch)
treebf308ff06cf9a5a8b6b0a82febaca3f5f5208e96
parentUpdate configuration info in readme (diff)
parentsway: refactor ipc_client_handle_command() (diff)
downloadsway-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.c63
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; 492exit_cleanup:
486 free(buf); 493 free(buf);
494 return;
487} 495}
488 496
489bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length) { 497bool 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