ustcomm: move function to destroy app socket to ustcomm
[ust.git] / libust / tracectl.c
index 7c65e3f82119496c6a608283c78c27ab1cc8eff4..47ca740781ebb0528c80d62c9e397702b8e415dc 100644 (file)
@@ -55,6 +55,9 @@ struct tracecmd { /* no padding */
        uint16_t command;
 };
 
+/* volatile because shared between the listener and the main thread */
+volatile sig_atomic_t buffers_to_export = 0;
+
 //struct listener_arg {
 //     int pipe_fd;
 //};
@@ -138,10 +141,39 @@ void notif_cb(void)
        }
 }
 
-static void inform_consumer_daemon(void)
+/* Ask the daemon to collect a trace called trace_name and being
+ * produced by this pid.
+ *
+ * The trace must be at least allocated. (It can also be started.)
+ * This is because _ltt_trace_find is used.
+ */
+
+static void inform_consumer_daemon(const char *trace_name)
 {
-       ustcomm_request_consumer(getpid(), "metadata");
-       ustcomm_request_consumer(getpid(), "ust");
+       int i;
+       struct ltt_trace_struct *trace;
+       pid_t pid = getpid();
+       int result;
+
+       ltt_lock_traces();
+
+       trace = _ltt_trace_find(trace_name);
+       if(trace == NULL) {
+               WARN("inform_consumer_daemon: could not find trace \"%s\"; it is probably already destroyed", trace_name);
+               goto finish;
+       }
+
+       for(i=0; i < trace->nr_channels; i++) {
+               result = ustcomm_request_consumer(pid, trace->channels[i].channel_name);
+               if(result == -1) {
+                       WARN("Failed to request collection for channel %s. Is the daemon available?", trace->channels[i].channel_name);
+                       /* continue even if fail */
+               }
+               buffers_to_export++;
+       }
+
+       finish:
+       ltt_unlock_traces();
 }
 
 void process_blocked_consumers(void)
@@ -292,7 +324,7 @@ void *listener_main(void *p)
                                return (void *)1;
                        }
 
-                       inform_consumer_daemon();
+                       inform_consumer_daemon(trace_name);
 
                        result = ltt_trace_start(trace_name);
                        if(result < 0) {
@@ -398,6 +430,8 @@ void *listener_main(void *p)
                                        break;
                                }
                        }
+
+                       buffers_to_export--;
                }
                else if(nth_token_is(recvbuf, "get_n_subbufs", 0) == 1) {
                        struct ltt_trace_struct *trace;
@@ -759,23 +793,6 @@ static int init_socket(void)
        return ustcomm_init_app(getpid(), &ustcomm_app);
 }
 
-/* FIXME: reenable this to delete socket file. */
-
-#if 0
-static void destroy_socket(void)
-{
-       int result;
-
-       if(mysocketfile[0] == '\0')
-               return;
-
-       result = unlink(mysocketfile);
-       if(result == -1) {
-               PERROR("unlink");
-       }
-}
-#endif
-
 static int init_signal_handler(void)
 {
        /* Attempt to handler SIGIO. If the main program wants to
@@ -954,12 +971,13 @@ static void __attribute__((constructor(1000))) init()
                        return;
                }
 
+               inform_consumer_daemon(trace_name);
+
                result = ltt_trace_start(trace_name);
                if(result < 0) {
                        ERR("ltt_trace_start failed");
                        return;
                }
-               inform_consumer_daemon();
        }
 
 
@@ -976,27 +994,26 @@ static void __attribute__((constructor(1000))) init()
 #if 0
 static void __attribute__((destructor)) fini()
 {
-       int result;
+//     int result;
 
        /* if trace running, finish it */
 
-       DBG("destructor stopping traces");
-
-       result = ltt_trace_stop("auto");
-       if(result == -1) {
-               ERR("ltt_trace_stop error");
-       }
-
-       result = ltt_trace_destroy("auto");
-       if(result == -1) {
-               ERR("ltt_trace_destroy error");
-       }
+//     DBG("destructor stopping traces");
 
-       destroy_socket();
+//     result = ltt_trace_stop("auto");
+//     if(result == -1) {
+//             ERR("ltt_trace_stop error");
+//     }
+//
+//     result = ltt_trace_destroy("auto");
+//     if(result == -1) {
+//             ERR("ltt_trace_destroy error");
+//     }
+//
+//     destroy_socket();
 }
 #endif
 
-#if 0
 static int trace_recording(void)
 {
        int retval = 0;
@@ -1016,22 +1033,20 @@ static int trace_recording(void)
        return retval;
 }
 
+#if 0
 static int have_consumer(void)
 {
        return !list_empty(&blocked_consumers);
 }
+#endif
 
-/* This destructor keeps the process alive for a few seconds in order
- * to leave time to ustd to consume its buffers.
- */
-
-int restarting_sleep(int secs)
+int restarting_usleep(useconds_t usecs)
 {
         struct timespec tv; 
         int result; 
  
-        tv.tv_sec = secs
-        tv.tv_nsec = 0; 
+        tv.tv_sec = 0
+        tv.tv_nsec = usecs * 1000; 
  
         do { 
                 result = nanosleep(&tv, &tv); 
@@ -1040,50 +1055,34 @@ int restarting_sleep(int secs)
        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()
 {
-//     struct ustcomm_ustd ustd;
-//     int result;
-//     sigset_t sigset;
-//
-//     result = sigemptyset(&sigset);
-//     if(result == -1) {
-//             perror("sigemptyset");
-//             return;
-//     }
-//     result = sigaddset(&sigset, SIGIO);
-//     if(result == -1) {
-//             perror("sigaddset");
-//             return;
-//     }
-//     result = sigprocmask(SIG_BLOCK, &sigset, NULL);
-//     if(result == -1) {
-//             perror("sigprocmask");
-//             return;
-//     }
-//
-//     if(trace_recording()) {
-//             if(!have_consumer()) {
-//                     /* Request listener creation. We've blocked SIGIO's in
-//                      * order to not interrupt sleep(), so we will miss the
-//                      * one sent by the daemon and therefore won't create
-//                      * the listener automatically.
-//                      */
-//                     create_listener();
-//
-                       printf("Keeping process alive for consumer daemon...\n");
-                       restarting_sleep(3);
-                       printf("Finally dying...\n");
-//             }
-//     }
-//
-//     result = sigprocmask(SIG_UNBLOCK, &sigset, NULL);
-//     if(result == -1) {
-//             perror("sigprocmask");
-//             return;
-//     }
+       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...");
+       }
 }
-#endif
 
 /* 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
@@ -1093,15 +1092,35 @@ static void __attribute__((destructor)) keepalive()
 
 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");
-       ltt_trace_alloc("auto");
-       ltt_trace_start("auto");
-       init_socket();
+       /* Delete all active connections */
+       ustcomm_close_all_connections(&ustcomm_app.server);
+
+       /* Delete all blocked consumers */
+       list_for_each_entry(bc, &blocked_consumers, list) {
+               free(deletable_bc);
+               deletable_bc = bc;
+               list_del(&bc->list);
+       }
+
        have_listener = 0;
        create_listener();
-       ustcomm_request_consumer(getpid(), "metadata");
-       ustcomm_request_consumer(getpid(), "ust");
+       init_socket();
+       ltt_trace_setup("auto");
+       result = ltt_trace_set_type("auto", "ustrelay");
+       if(result < 0) {
+               ERR("ltt_trace_set_type failed");
+               return (void *)1;
+       }
+
+       ltt_trace_alloc("auto");
+       ltt_trace_start("auto");
+       inform_consumer_daemon("auto");
 }
 
This page took 0.027031 seconds and 4 git commands to generate.