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 <mathieu.desnoyers@efficios.com>
* 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;
/*
*
* 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;
ust_lock_nocheck();
rcu_bp_before_fork();
+ lttng_ust_lock_fd_tracker();
}
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);