*/
static int sem_count = { 2 };
+/*
+ * Counting nesting within lttng-ust. Used to ensure that calling fork()
+ * from liblttng-ust does not execute the pre/post fork handlers.
+ */
+static int __thread lttng_ust_nest_count;
+
/*
* Info about socket and associated listener thread.
*/
extern void ltt_ring_buffer_client_discard_exit(void);
extern void ltt_ring_buffer_metadata_client_exit(void);
+/*
+ * Force a read (imply TLS fixup for dlopen) of TLS variables.
+ */
+static
+void lttng_fixup_nest_count_tls(void)
+{
+ asm volatile ("" : : "m" (lttng_ust_nest_count));
+}
+
static
int setup_local_apps(void)
{
* If the open failed because the file did not exist, try
* creating it ourself.
*/
+ lttng_ust_nest_count++;
pid = fork();
+ lttng_ust_nest_count--;
if (pid > 0) {
int status;
lttng_fixup_event_tls();
lttng_fixup_ringbuffer_tls();
lttng_fixup_vtid_tls();
+ lttng_fixup_nest_count_tls();
/*
* We want precise control over the order in which we construct
sigfillset(&sig_all_blocked);
ret = pthread_sigmask(SIG_SETMASK, &sig_all_blocked, &orig_parent_mask);
if (ret) {
- PERROR("pthread_sigmask: %s", strerror(ret));
+ ERR("pthread_sigmask: %s", strerror(ret));
}
ret = pthread_create(&global_apps.ust_listener, NULL,
ust_listener_thread, &global_apps);
-
+ if (ret) {
+ ERR("pthread_create global: %s", strerror(ret));
+ }
if (local_apps.allowed) {
ret = pthread_create(&local_apps.ust_listener, NULL,
ust_listener_thread, &local_apps);
+ if (ret) {
+ ERR("pthread_create local: %s", strerror(ret));
+ }
} else {
handle_register_done(&local_apps);
}
/* Restore original signal mask in parent */
ret = pthread_sigmask(SIG_SETMASK, &orig_parent_mask, NULL);
if (ret) {
- PERROR("pthread_sigmask: %s", strerror(ret));
+ ERR("pthread_sigmask: %s", strerror(ret));
}
switch (timeout_mode) {
/* cancel threads */
ret = pthread_cancel(global_apps.ust_listener);
if (ret) {
- ERR("Error cancelling global ust listener thread");
+ ERR("Error cancelling global ust listener thread: %s",
+ strerror(ret));
}
if (local_apps.allowed) {
ret = pthread_cancel(local_apps.ust_listener);
if (ret) {
- ERR("Error cancelling local ust listener thread");
+ ERR("Error cancelling local ust listener thread: %s",
+ strerror(ret));
}
}
/*
sigset_t all_sigs;
int ret;
+ if (lttng_ust_nest_count)
+ return;
/* Disable signals */
sigfillset(&all_sigs);
ret = sigprocmask(SIG_BLOCK, &all_sigs, save_sigset);
void ust_after_fork_parent(sigset_t *restore_sigset)
{
+ if (lttng_ust_nest_count)
+ return;
DBG("process %d", getpid());
rcu_bp_after_fork_parent();
/* Release mutexes and reenable signals */
*/
void ust_after_fork_child(sigset_t *restore_sigset)
{
+ if (lttng_ust_nest_count)
+ return;
DBG("process %d", getpid());
/* Release urcu mutexes */
rcu_bp_after_fork_child();