X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=liblttng-ust%2Flttng-ust-comm.c;h=3df2adc6f96e0b0b16189efe6497509ea845e3da;hb=2932a87f05ceaf44c3a0b51fa6bdecd4b13c113d;hp=5df33f5f789e529a86249899b0ff4a2655757c7c;hpb=d58d145447ffcc9497801769e1fe754b30dca5b8;p=lttng-ust.git diff --git a/liblttng-ust/lttng-ust-comm.c b/liblttng-ust/lttng-ust-comm.c index 5df33f5f..3df2adc6 100644 --- a/liblttng-ust/lttng-ust-comm.c +++ b/liblttng-ust/lttng-ust-comm.c @@ -68,9 +68,14 @@ static int initialized; * * ust_exit_mutex must never nest in ust_mutex. * + * ust_fork_mutex must never nest in ust_mutex. + * * ust_mutex_nest is a per-thread nesting counter, allowing the perf * counter lazy initialization called by events within the statedump, * which traces while the ust_mutex is held. + * + * ust_lock nests within the dynamic loader lock (within glibc) because + * it is taken within the library constructor. */ static pthread_mutex_t ust_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -86,6 +91,14 @@ static DEFINE_URCU_TLS(int, ust_mutex_nest); */ static pthread_mutex_t ust_exit_mutex = PTHREAD_MUTEX_INITIALIZER; +/* + * ust_fork_mutex protects base address statedump tracing against forks. It + * prevents the dynamic loader lock to be taken (by base address statedump + * tracing) while a fork is happening, thus preventing deadlock issues with + * the dynamic loader lock. + */ +static pthread_mutex_t ust_fork_mutex = PTHREAD_MUTEX_INITIALIZER; + /* Should the ust comm thread quit ? */ static int lttng_ust_comm_should_quit; @@ -506,7 +519,9 @@ void handle_pending_statedump(struct sock_info *sock_info) if (ctor_passed && sock_info->statedump_pending) { sock_info->statedump_pending = 0; + pthread_mutex_lock(&ust_fork_mutex); lttng_handle_pending_statedump(sock_info); + pthread_mutex_unlock(&ust_fork_mutex); } } @@ -1627,6 +1642,9 @@ void ust_before_fork(sigset_t *save_sigset) if (ret == -1) { PERROR("sigprocmask"); } + + pthread_mutex_lock(&ust_fork_mutex); + ust_lock_nocheck(); rcu_bp_before_fork(); } @@ -1637,6 +1655,9 @@ static void ust_after_fork_common(sigset_t *restore_sigset) DBG("process %d", getpid()); ust_unlock(); + + pthread_mutex_unlock(&ust_fork_mutex); + /* Restore signals */ ret = sigprocmask(SIG_SETMASK, restore_sigset, NULL); if (ret == -1) {