diff options
author | Jean-Philippe Andre <jp.andre@samsung.com> | 2013-11-29 11:45:19 +0900 |
---|---|---|
committer | Jean-Philippe Andre <jp.andre@samsung.com> | 2013-11-29 15:47:57 +0900 |
commit | 62093d99d4d73668c1133b13fb496baf5e56be7a (patch) | |
tree | 7ff8cd3d38e1743490cc3bfe9e63d66ef26124ba /src/lib/evas/cserve2/evas_cs2_client.c | |
parent | 4f33c81bdbf94cf15b7cf56fcb05b849f8f99581 (diff) |
evas/cserve2: Fix interrupt on select in edje_cc
Summary:
Block SIGCHLD during select().
This fixes a bug with edje_cc when EVAS_CSERVE2=1: Fixes T464.
select() used to return prematurately with EINTR because the
app received some unexpected signals. In particular SIGCHLD
is received when a child terminates, but this is not a reason
to cancel the image load.
In theory, all blocked signals in pselect() should be pending
until pselect returns, so any SIGCHLD should still trigger
the app's signal handler.
Reviewers: cedric
CC: raster, cedric
Maniphest Tasks: T464
Differential Revision: https://phab.enlightenment.org/D357
Diffstat (limited to '')
-rw-r--r-- | src/lib/evas/cserve2/evas_cs2_client.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/src/lib/evas/cserve2/evas_cs2_client.c b/src/lib/evas/cserve2/evas_cs2_client.c index 0d5fe2cefc..c5ef5948a4 100644 --- a/src/lib/evas/cserve2/evas_cs2_client.c +++ b/src/lib/evas/cserve2/evas_cs2_client.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <sys/stat.h> | 8 | #include <sys/stat.h> |
9 | #include <unistd.h> | 9 | #include <unistd.h> |
10 | #include <fcntl.h> | 10 | #include <fcntl.h> |
11 | #include <signal.h> | ||
11 | 12 | ||
12 | #include <Eina.h> | 13 | #include <Eina.h> |
13 | 14 | ||
@@ -600,6 +601,14 @@ _server_dispatch_until(unsigned int rid) | |||
600 | { | 601 | { |
601 | Eina_Bool failed; | 602 | Eina_Bool failed; |
602 | unsigned int rrid; | 603 | unsigned int rrid; |
604 | sigset_t sigmask; | ||
605 | |||
606 | // We want to block some signals from interrupting pselect(). | ||
607 | // If the kernel implements TIF_RESTORE_SIGMASK, the | ||
608 | // signal handlers should be called right after pselect | ||
609 | // SIGCHLD: apps can have children that just terminated | ||
610 | sigprocmask(0, NULL, &sigmask); | ||
611 | sigaddset(&sigmask, SIGCHLD); | ||
603 | 612 | ||
604 | while (1) | 613 | while (1) |
605 | { | 614 | { |
@@ -609,7 +618,7 @@ _server_dispatch_until(unsigned int rid) | |||
609 | else if (failed) | 618 | else if (failed) |
610 | { | 619 | { |
611 | fd_set rfds; | 620 | fd_set rfds; |
612 | struct timeval tv; | 621 | struct timespec ts; |
613 | int sel; | 622 | int sel; |
614 | 623 | ||
615 | if (socketfd == -1) | 624 | if (socketfd == -1) |
@@ -625,9 +634,9 @@ _server_dispatch_until(unsigned int rid) | |||
625 | //DBG("Waiting for request %d...", rid); | 634 | //DBG("Waiting for request %d...", rid); |
626 | FD_ZERO(&rfds); | 635 | FD_ZERO(&rfds); |
627 | FD_SET(socketfd, &rfds); | 636 | FD_SET(socketfd, &rfds); |
628 | tv.tv_sec = TIMEOUT / 1000; | 637 | ts.tv_sec = TIMEOUT / 1000; |
629 | tv.tv_usec = TIMEOUT * 1000; | 638 | ts.tv_nsec = (TIMEOUT % 1000) * 1000000; |
630 | sel = select(socketfd + 1, &rfds, NULL, NULL, &tv); | 639 | sel = pselect(socketfd + 1, &rfds, NULL, NULL, &ts, &sigmask); |
631 | if (sel == -1) | 640 | if (sel == -1) |
632 | { | 641 | { |
633 | ERR("select() failed: [%d] %s", errno, strerror(errno)); | 642 | ERR("select() failed: [%d] %s", errno, strerror(errno)); |
@@ -638,6 +647,11 @@ _server_dispatch_until(unsigned int rid) | |||
638 | */ | 647 | */ |
639 | if (errno == EINTR) | 648 | if (errno == EINTR) |
640 | { | 649 | { |
650 | /* FIXME: Actually we might want to cancel our request | ||
651 | * ONLY when we received a SIGINT, but at this point | ||
652 | * there is no way we can know which signal we got. | ||
653 | * So we assume SIGINT and abandon this request. | ||
654 | */ | ||
641 | DBG("giving up on request %d after interrupt", rid); | 655 | DBG("giving up on request %d after interrupt", rid); |
642 | return EINA_FALSE; | 656 | return EINA_FALSE; |
643 | } | 657 | } |