Fix: Enable event after start command
authorDavid Goulet <dgoulet@efficios.com>
Thu, 8 Nov 2012 19:08:28 +0000 (14:08 -0500)
committerDavid Goulet <dgoulet@efficios.com>
Thu, 8 Nov 2012 20:00:30 +0000 (15:00 -0500)
Refer to the bug tracker for more information on this bug. In a
nutshell, it was not possible to enable channel/event after a start
command has been issued (for both kernel and UST).

Note that it is still NOT possible to enable a channel after a start but
the use case here was the following:

$ lttng create
$ lttng start
$ lttng enable-event -a -u (or -k)

The first starts does NOT create a kernel or UST session so the
following enable event creates the session for the given domain but
failed to start the session after.

https://bugs.lttng.org/issues/346
https://bugs.lttng.org/issues/394

Fixes #346 #394

Signed-off-by: David Goulet <dgoulet@efficios.com>
src/bin/lttng-sessiond/cmd.c
src/bin/lttng-sessiond/session.h
src/bin/lttng-sessiond/trace-kernel.h

index 46a758e27eab8f9b01c502256bde42a60b32702d..e4e03e88cd3905a0e1321eed49199cc0ab5368e1 100644 (file)
@@ -670,6 +670,71 @@ error:
        return ret;
 }
 
+/*
+ * Start a kernel session by opening all necessary streams.
+ */
+static int start_kernel_session(struct ltt_kernel_session *ksess, int wpipe)
+{
+       int ret;
+       struct ltt_kernel_channel *kchan;
+
+       /* Open kernel metadata */
+       if (ksess->metadata == NULL) {
+               ret = kernel_open_metadata(ksess);
+               if (ret < 0) {
+                       ret = LTTNG_ERR_KERN_META_FAIL;
+                       goto error;
+               }
+       }
+
+       /* Open kernel metadata stream */
+       if (ksess->metadata_stream_fd < 0) {
+               ret = kernel_open_metadata_stream(ksess);
+               if (ret < 0) {
+                       ERR("Kernel create metadata stream failed");
+                       ret = LTTNG_ERR_KERN_STREAM_FAIL;
+                       goto error;
+               }
+       }
+
+       /* For each channel */
+       cds_list_for_each_entry(kchan, &ksess->channel_list.head, list) {
+               if (kchan->stream_count == 0) {
+                       ret = kernel_open_channel_stream(kchan);
+                       if (ret < 0) {
+                               ret = LTTNG_ERR_KERN_STREAM_FAIL;
+                               goto error;
+                       }
+                       /* Update the stream global counter */
+                       ksess->stream_count_global += ret;
+               }
+       }
+
+       /* Setup kernel consumer socket and send fds to it */
+       ret = init_kernel_tracing(ksess);
+       if (ret < 0) {
+               ret = LTTNG_ERR_KERN_START_FAIL;
+               goto error;
+       }
+
+       /* This start the kernel tracing */
+       ret = kernel_start_session(ksess);
+       if (ret < 0) {
+               ret = LTTNG_ERR_KERN_START_FAIL;
+               goto error;
+       }
+
+       /* Quiescent wait after starting trace */
+       kernel_wait_quiescent(wpipe);
+
+       ksess->started = 1;
+
+       ret = LTTNG_OK;
+
+error:
+       return ret;
+}
+
 /*
  * Command LTTNG_DISABLE_CHANNEL processed by the client thread.
  */
@@ -765,7 +830,19 @@ int cmd_enable_channel(struct ltt_session *session,
                        goto error;
                }
 
-               kernel_wait_quiescent(kernel_tracer_fd);
+               kernel_wait_quiescent(wpipe);
+
+               /*
+                * If the session was previously started, start as well this newly
+                * created kernel session so the events/channels enabled *after* the
+                * start actually work.
+                */
+               if (session->started && !session->kernel_session->started) {
+                       ret = start_kernel_session(session->kernel_session, wpipe);
+                       if (ret != LTTNG_OK) {
+                               goto error;
+                       }
+               }
                break;
        }
        case LTTNG_DOMAIN_UST:
@@ -780,6 +857,17 @@ int cmd_enable_channel(struct ltt_session *session,
                } else {
                        ret = channel_ust_enable(usess, domain, uchan);
                }
+
+               /* Start the UST session if the session was already started. */
+               if (session->started && !usess->start_trace) {
+                       ret = ust_app_start_trace_all(usess);
+                       if (ret < 0) {
+                               ret = LTTNG_ERR_UST_START_FAIL;
+                               goto error;
+                       }
+                       ret = LTTNG_OK;
+                       usess->start_trace = 1;
+               }
                break;
        }
 #if 0
@@ -1378,7 +1466,6 @@ int cmd_start_trace(struct ltt_session *session)
        int ret;
        struct ltt_kernel_session *ksession;
        struct ltt_ust_session *usess;
-       struct ltt_kernel_channel *kchan;
 
        assert(session);
 
@@ -1402,54 +1489,10 @@ int cmd_start_trace(struct ltt_session *session)
 
        /* Kernel tracing */
        if (ksession != NULL) {
-               /* Open kernel metadata */
-               if (ksession->metadata == NULL) {
-                       ret = kernel_open_metadata(ksession);
-                       if (ret < 0) {
-                               ret = LTTNG_ERR_KERN_META_FAIL;
-                               goto error;
-                       }
-               }
-
-               /* Open kernel metadata stream */
-               if (ksession->metadata_stream_fd < 0) {
-                       ret = kernel_open_metadata_stream(ksession);
-                       if (ret < 0) {
-                               ERR("Kernel create metadata stream failed");
-                               ret = LTTNG_ERR_KERN_STREAM_FAIL;
-                               goto error;
-                       }
-               }
-
-               /* For each channel */
-               cds_list_for_each_entry(kchan, &ksession->channel_list.head, list) {
-                       if (kchan->stream_count == 0) {
-                               ret = kernel_open_channel_stream(kchan);
-                               if (ret < 0) {
-                                       ret = LTTNG_ERR_KERN_STREAM_FAIL;
-                                       goto error;
-                               }
-                               /* Update the stream global counter */
-                               ksession->stream_count_global += ret;
-                       }
-               }
-
-               /* Setup kernel consumer socket and send fds to it */
-               ret = init_kernel_tracing(ksession);
-               if (ret < 0) {
-                       ret = LTTNG_ERR_KERN_START_FAIL;
-                       goto error;
-               }
-
-               /* This start the kernel tracing */
-               ret = kernel_start_session(ksession);
-               if (ret < 0) {
-                       ret = LTTNG_ERR_KERN_START_FAIL;
+               ret = start_kernel_session(ksession, kernel_tracer_fd);
+               if (ret != LTTNG_OK) {
                        goto error;
                }
-
-               /* Quiescent wait after starting trace */
-               kernel_wait_quiescent(kernel_tracer_fd);
        }
 
        /* Flag session that trace should start automatically */
@@ -1463,6 +1506,8 @@ int cmd_start_trace(struct ltt_session *session)
                }
        }
 
+       session->started = 1;
+
        ret = LTTNG_OK;
 
 error:
@@ -1519,6 +1564,8 @@ int cmd_stop_trace(struct ltt_session *session)
                }
 
                kernel_wait_quiescent(kernel_tracer_fd);
+
+               ksession->started = 0;
        }
 
        if (usess) {
@@ -1531,6 +1578,8 @@ int cmd_stop_trace(struct ltt_session *session)
                }
        }
 
+       session->started = 0;
+
        ret = LTTNG_OK;
 
 error:
index 1b40373e925a8336ebc3359f914ab10204beedb1..8a3504f43b925c5389a69682e57e9be2c735a46a 100644 (file)
@@ -85,6 +85,9 @@ struct ltt_session {
 
        /* Indicates whether or not we have to spawn consumer(s) */
        unsigned int start_consumer;
+
+       /* Did a start command occured before the kern/ust session creation? */
+       unsigned int started;
 };
 
 /* Prototypes */
index 96a3664b4158d8a78f13053bfe75ab7a83d9272b..ed5b3318921248250f135806e8450f3bf040f790 100644 (file)
@@ -110,6 +110,8 @@ struct ltt_kernel_session {
        struct consumer_output *tmp_consumer;
        /* Tracing session id */
        unsigned int id;
+       /* Session is started and active */
+       unsigned int started;
 };
 
 /*
This page took 0.040008 seconds and 4 git commands to generate.