From 105f9cd955808d491186e72ee6e760476a9647c1 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Mon, 17 Aug 2015 09:50:34 -0700 Subject: [PATCH] Fix: application exit race with pthread cancel Listener threads can be cancelled with ust lock held, which can hang the following ust cleanup routine, because tracepoint probe unregister needs to take the ust lock. Fix this by disabling pthread cancellation for the entire duration of the ust lock. Signed-off-by: Mathieu Desnoyers --- liblttng-ust/lttng-ust-comm.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/liblttng-ust/lttng-ust-comm.c b/liblttng-ust/lttng-ust-comm.c index 7d885a55..e1426139 100644 --- a/liblttng-ust/lttng-ust-comm.c +++ b/liblttng-ust/lttng-ust-comm.c @@ -114,8 +114,15 @@ static int lttng_ust_comm_should_quit; int ust_lock(void) { sigset_t sig_all_blocked, orig_mask; - int ret; + int ret, oldstate; + ret = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); + if (ret) { + ERR("pthread_setcancelstate: %s", strerror(ret)); + } + if (oldstate != PTHREAD_CANCEL_ENABLE) { + ERR("pthread_setcancelstate: unexpected oldstate"); + } sigfillset(&sig_all_blocked); ret = pthread_sigmask(SIG_SETMASK, &sig_all_blocked, &orig_mask); if (ret) { @@ -143,8 +150,15 @@ int ust_lock(void) void ust_lock_nocheck(void) { sigset_t sig_all_blocked, orig_mask; - int ret; + int ret, oldstate; + ret = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); + if (ret) { + ERR("pthread_setcancelstate: %s", strerror(ret)); + } + if (oldstate != PTHREAD_CANCEL_ENABLE) { + ERR("pthread_setcancelstate: unexpected oldstate"); + } sigfillset(&sig_all_blocked); ret = pthread_sigmask(SIG_SETMASK, &sig_all_blocked, &orig_mask); if (ret) { @@ -164,7 +178,7 @@ void ust_lock_nocheck(void) void ust_unlock(void) { sigset_t sig_all_blocked, orig_mask; - int ret; + int ret, oldstate; sigfillset(&sig_all_blocked); ret = pthread_sigmask(SIG_SETMASK, &sig_all_blocked, &orig_mask); @@ -177,6 +191,13 @@ void ust_unlock(void) if (ret) { ERR("pthread_sigmask: %s", strerror(ret)); } + ret = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); + if (ret) { + ERR("pthread_setcancelstate: %s", strerror(ret)); + } + if (oldstate != PTHREAD_CANCEL_DISABLE) { + ERR("pthread_setcancelstate: unexpected oldstate"); + } } /* -- 2.34.1