From: Mathieu Desnoyers Date: Fri, 4 Oct 2019 14:07:03 +0000 (-0400) Subject: Fix: Lock FD tracker across fork X-Git-Tag: v2.9.7~6 X-Git-Url: http://git.liburcu.org/?p=lttng-ust.git;a=commitdiff_plain;h=57349053b60a11a6ba741fd88f70354e9f5d7cb1 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 26c2e290..8b03125e 100644 --- a/liblttng-ust/lttng-ust-comm.c +++ b/liblttng-ust/lttng-ust-comm.c @@ -81,6 +81,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; @@ -2024,6 +2026,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) @@ -2031,6 +2034,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);