+ ltt_trace_setup("auto");
+ result = ltt_trace_set_type("auto", "ustrelay");
+ if (result < 0) {
+ ERR("ltt_trace_set_type failed");
+ return;
+ }
+
+ ltt_trace_alloc("auto");
+ ltt_trace_start("auto");
+ inform_consumer_daemon("auto");
+}
+
+void ust_before_fork(ust_fork_info_t *fork_info)
+{
+ /* Disable signals. This is to avoid that the child
+ * intervenes before it is properly setup for tracing. It is
+ * safer to disable all signals, because then we know we are not
+ * breaking anything by restoring the original mask.
+ */
+ sigset_t all_sigs;
+ int result;
+
+ /* FIXME:
+ - only do this if tracing is active
+ */
+
+ /* Disable signals */
+ sigfillset(&all_sigs);
+ result = sigprocmask(SIG_BLOCK, &all_sigs, &fork_info->orig_sigs);
+ if (result == -1) {
+ PERROR("sigprocmask");
+ return;
+ }
+
+ /*
+ * Take the fork lock to make sure we are not in the middle of
+ * something in the listener thread.
+ */
+ pthread_mutex_lock(&listener_thread_data_mutex);
+ /*
+ * Hold listen_sock_mutex to protect from listen_sock teardown.
+ */
+ pthread_mutex_lock(&listen_sock_mutex);
+ rcu_bp_before_fork();
+}
+
+/* Don't call this function directly in a traced program */
+static void ust_after_fork_common(ust_fork_info_t *fork_info)
+{
+ int result;
+
+ pthread_mutex_unlock(&listen_sock_mutex);
+ pthread_mutex_unlock(&listener_thread_data_mutex);
+
+ /* Restore signals */
+ result = sigprocmask(SIG_SETMASK, &fork_info->orig_sigs, NULL);
+ if (result == -1) {
+ PERROR("sigprocmask");
+ return;
+ }
+}
+
+void ust_after_fork_parent(ust_fork_info_t *fork_info)
+{
+ rcu_bp_after_fork_parent();
+ /* Release mutexes and reenable signals */
+ ust_after_fork_common(fork_info);
+}
+
+void ust_after_fork_child(ust_fork_info_t *fork_info)
+{
+ /* Release urcu mutexes */
+ rcu_bp_after_fork_child();
+
+ /* Sanitize the child */
+ ust_fork();
+
+ /* Then release mutexes and reenable signals */
+ ust_after_fork_common(fork_info);