+
+int restarting_usleep(useconds_t usecs)
+{
+ struct timespec tv;
+ int result;
+
+ tv.tv_sec = 0;
+ tv.tv_nsec = usecs * 1000;
+
+ do {
+ result = nanosleep(&tv, &tv);
+ } while(result == -1 && errno == EINTR);
+
+ return result;
+}
+
+/* This destructor keeps the process alive for a few seconds in order
+ * to leave time to ustd to connect to its buffers. This is necessary
+ * for programs whose execution is very short. It is also useful in all
+ * programs when tracing is started close to the end of the program
+ * execution.
+ *
+ * FIXME: For now, this only works for the first trace created in a
+ * process.
+ */
+
+static void __attribute__((destructor)) keepalive()
+{
+ if(trace_recording() && buffers_to_export) {
+ int total = 0;
+ DBG("Keeping process alive for consumer daemon...");
+ while(buffers_to_export) {
+ const int interv = 200000;
+ restarting_usleep(interv);
+ total += interv;
+
+ if(total >= 3000000) {
+ WARN("non-consumed buffers remaining after wait limit; not waiting anymore");
+ break;
+ }
+ }
+ DBG("Finally dying...");
+ }
+
+ destroy_traces();
+
+ ustcomm_fini_app(&ustcomm_app);
+}
+
+void ust_potential_exec(void)
+{
+ trace_mark(ust, potential_exec, MARK_NOARGS);
+
+ DBG("test");
+
+ keepalive();
+}
+
+/* Notify ust that there was a fork. This needs to be called inside
+ * the new process, anytime a process whose memory is not shared with
+ * the parent is created. If this function is not called, the events
+ * of the new process will not be collected.
+ */
+
+void ust_fork(void)
+{
+ struct blocked_consumer *bc;
+ struct blocked_consumer *deletable_bc = NULL;
+ int result;
+
+ DBG("ust: forking");
+ ltt_trace_stop("auto");
+ ltt_trace_destroy("auto");
+ /* Delete all active connections */
+ ustcomm_close_all_connections(&ustcomm_app.server);
+
+ /* Delete all blocked consumers */
+ list_for_each_entry(bc, &blocked_consumers, list) {
+ close(bc->fd_producer);
+ close(bc->fd_consumer);
+ free(deletable_bc);
+ deletable_bc = bc;
+ list_del(&bc->list);
+ }
+
+ have_listener = 0;
+ create_listener();
+ init_socket();
+ 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");
+}
+