From c1be081a2f016fb6dcaef1d471389ede3aa00103 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Fri, 4 Oct 2019 10:07:03 -0400 Subject: [PATCH] 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 --- liblttng-ust-comm/lttng-ust-fd-tracker.c | 3 +++ liblttng-ust/lttng-ust-comm.c | 4 ++++ 2 files changed, 7 insertions(+) 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 e392e460..47ba36e5 100644 --- a/liblttng-ust/lttng-ust-comm.c +++ b/liblttng-ust/lttng-ust-comm.c @@ -86,6 +86,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; @@ -2065,6 +2067,7 @@ void ust_before_fork(sigset_t *save_sigset) ust_lock_nocheck(); urcu_bp_before_fork(); + lttng_ust_lock_fd_tracker(); } static void ust_after_fork_common(sigset_t *restore_sigset) @@ -2072,6 +2075,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); -- 2.34.1