From: Mathieu Desnoyers Date: Fri, 4 Oct 2019 14:07:03 +0000 (-0400) Subject: Fix: Lock FD tracker across fork X-Git-Tag: v2.10.6~6 X-Git-Url: http://git.liburcu.org/?p=lttng-ust.git;a=commitdiff_plain;h=791bf2738ef251049e65eb8750a8fe3a55400dcc Fix: Lock FD tracker across fork If fork() is performed while other threads are holding the fd tracker lock, it will stay in locked state in the child process and eventually cause a deadlock. One way to solve this is to hold the fd tracker lock across fork(), in the same way we do for the ust_lock. This ensures no other threads are holding that lock in the parent, and therefore provides a consistent lock state in the child. Fixes: #1199 Fixes: #1200 Signed-off-by: Mathieu Desnoyers --- diff --git a/liblttng-ust-comm/lttng-ust-fd-tracker.c b/liblttng-ust-comm/lttng-ust-fd-tracker.c index 1bc186bf..28289591 100644 --- a/liblttng-ust-comm/lttng-ust-fd-tracker.c +++ b/liblttng-ust-comm/lttng-ust-fd-tracker.c @@ -61,6 +61,9 @@ * Protect the lttng_fd_set. Nests within the ust_lock, and therefore * within the libc dl lock. Therefore, we need to fixup the TLS before * nesting into this lock. + * + * The ust_safe_guard_fd_mutex nests within the ust_mutex. This mutex + * is also held across fork. */ static pthread_mutex_t ust_safe_guard_fd_mutex = PTHREAD_MUTEX_INITIALIZER; /* diff --git a/liblttng-ust/lttng-ust-comm.c b/liblttng-ust/lttng-ust-comm.c index f47ae784..fe33c5d7 100644 --- a/liblttng-ust/lttng-ust-comm.c +++ b/liblttng-ust/lttng-ust-comm.c @@ -82,6 +82,8 @@ static int initialized; * * ust_lock nests within the dynamic loader lock (within glibc) because * it is taken within the library constructor. + * + * The ust fd tracker lock nests within the ust_mutex. */ static pthread_mutex_t ust_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -2040,6 +2042,7 @@ void ust_before_fork(sigset_t *save_sigset) ust_lock_nocheck(); rcu_bp_before_fork(); + lttng_ust_lock_fd_tracker(); } static void ust_after_fork_common(sigset_t *restore_sigset) @@ -2047,6 +2050,7 @@ static void ust_after_fork_common(sigset_t *restore_sigset) int ret; DBG("process %d", getpid()); + lttng_ust_unlock_fd_tracker(); ust_unlock(); pthread_mutex_unlock(&ust_fork_mutex);