From: Mathieu Desnoyers Date: Mon, 6 Jul 2015 21:09:32 +0000 (-0400) Subject: Fix: handle sys_futex EINTR and EWOULDBLOCK X-Git-Tag: v2.5.6~5 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=faccc28ac2aa16092117eae5181fce79fff98396;p=lttng-ust.git Fix: handle sys_futex EINTR and EWOULDBLOCK Handling sys_futex EINTR allows us to retry waiting on the futex immediately if we are interrupted by a signal without having to try connecting to the session daemon. This should not impact correctness though, as the wait scheme would simply try to connect, fail, and try waiting again. Also handle errors on FUTEX_WAKE. Signed-off-by: Mathieu Desnoyers --- diff --git a/liblttng-ust/lttng-ust-comm.c b/liblttng-ust/lttng-ust-comm.c index 3800ba68..50e76765 100644 --- a/liblttng-ust/lttng-ust-comm.c +++ b/liblttng-ust/lttng-ust-comm.c @@ -1117,8 +1117,6 @@ error: static void wait_for_sessiond(struct sock_info *sock_info) { - int ret; - if (ust_lock()) { goto quit; } @@ -1134,23 +1132,32 @@ void wait_for_sessiond(struct sock_info *sock_info) DBG("Waiting for %s apps sessiond", sock_info->name); /* Wait for futex wakeup */ - if (uatomic_read((int32_t *) sock_info->wait_shm_mmap) == 0) { - ret = futex_async((int32_t *) sock_info->wait_shm_mmap, - FUTEX_WAIT, 0, NULL, NULL, 0); - if (ret < 0) { - if (errno == EFAULT) { - wait_poll_fallback = 1; - DBG( + if (uatomic_read((int32_t *) sock_info->wait_shm_mmap)) + goto end_wait; + + while (futex_async((int32_t *) sock_info->wait_shm_mmap, + FUTEX_WAIT, 0, NULL, NULL, 0)) { + switch (errno) { + case EWOULDBLOCK: + /* Value already changed. */ + goto end_wait; + case EINTR: + /* Retry if interrupted by signal. */ + break; /* Get out of switch. */ + case EFAULT: + wait_poll_fallback = 1; + DBG( "Linux kernels 2.6.33 to 3.0 (with the exception of stable versions) " "do not support FUTEX_WAKE on read-only memory mappings correctly. " "Please upgrade your kernel " "(fix is commit 9ea71503a8ed9184d2d0b8ccc4d269d05f7940ae in Linux kernel " "mainline). LTTng-UST will use polling mode fallback."); - if (ust_debug()) - PERROR("futex"); - } + if (ust_debug()) + PERROR("futex"); + goto end_wait; } } +end_wait: return; quit: diff --git a/tests/ust-basic-tracing/ust-basic-tracing.c b/tests/ust-basic-tracing/ust-basic-tracing.c index 7bfeb5bc..cc0fb89b 100644 --- a/tests/ust-basic-tracing/ust-basic-tracing.c +++ b/tests/ust-basic-tracing/ust-basic-tracing.c @@ -659,8 +659,11 @@ int update_futex(int fd, int active) if (active) { uatomic_set((int32_t *) wait_shm_mmap, 1); - futex_async((int32_t *) wait_shm_mmap, FUTEX_WAKE, - INT_MAX, NULL, NULL, 0); + if (futex_async((int32_t *) wait_shm_mmap, FUTEX_WAKE, + INT_MAX, NULL, NULL, 0) < 0) { + perror("futex_async"); + goto error; + } } else { uatomic_set((int32_t *) wait_shm_mmap, 0); } diff --git a/tests/ust-multi-test/ust-multi-test.c b/tests/ust-multi-test/ust-multi-test.c index 77711540..c003c5a9 100644 --- a/tests/ust-multi-test/ust-multi-test.c +++ b/tests/ust-multi-test/ust-multi-test.c @@ -655,8 +655,11 @@ int update_futex(int fd, int active) if (active) { uatomic_set((int32_t *) wait_shm_mmap, 1); - futex_async((int32_t *) wait_shm_mmap, FUTEX_WAKE, - INT_MAX, NULL, NULL, 0); + if (futex_async((int32_t *) wait_shm_mmap, FUTEX_WAKE, + INT_MAX, NULL, NULL, 0) < 0) { + perror("futex_async"); + goto error; + } } else { uatomic_set((int32_t *) wait_shm_mmap, 0); }