Fix: consumer should await for initial streams
[lttng-tools.git] / src / common / ust-consumer / ust-consumer.c
index 9cafe398e1493be918896b8bc803c14e0f98e242..ad4b014c6f08dc09f4e47b22e19cbd47330ec5ae 100644 (file)
@@ -92,6 +92,11 @@ int lttng_ustconsumer_get_produced_snapshot(
        return ret;
 }
 
+/*
+ * Receive command from session daemon and process it.
+ *
+ * Return 1 on success else a negative value or 0.
+ */
 int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                int sock, struct pollfd *consumer_sockpoll)
 {
@@ -102,7 +107,7 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
        if (ret != sizeof(msg)) {
                DBG("Consumer received unexpected message size %zd (expects %zu)",
                        ret, sizeof(msg));
-               lttng_consumer_send_error(ctx, CONSUMERD_ERROR_RECV_FD);
+               lttng_consumer_send_error(ctx, LTTCOMM_CONSUMERD_ERROR_RECV_FD);
                return ret;
        }
        if (msg.cmd_type == LTTNG_CONSUMER_STOP) {
@@ -135,7 +140,7 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                }
                ret = lttcomm_recv_fds_unix_sock(sock, fds, nb_fd);
                if (ret != sizeof(fds)) {
-                       lttng_consumer_send_error(ctx, CONSUMERD_ERROR_RECV_FD);
+                       lttng_consumer_send_error(ctx, LTTCOMM_CONSUMERD_ERROR_RECV_FD);
                        rcu_read_unlock();
                        return ret;
                }
@@ -145,9 +150,10 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                new_channel = consumer_allocate_channel(msg.u.channel.channel_key,
                                fds[0], -1,
                                msg.u.channel.mmap_len,
-                               msg.u.channel.max_sb_size);
+                               msg.u.channel.max_sb_size,
+                               msg.u.channel.nb_init_streams);
                if (new_channel == NULL) {
-                       lttng_consumer_send_error(ctx, CONSUMERD_OUTFD_ERROR);
+                       lttng_consumer_send_error(ctx, LTTCOMM_CONSUMERD_OUTFD_ERROR);
                        goto end_nosignal;
                }
                if (ctx->on_recv_channel != NULL) {
@@ -178,7 +184,7 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                }
                ret = lttcomm_recv_fds_unix_sock(sock, fds, nb_fd);
                if (ret != sizeof(fds)) {
-                       lttng_consumer_send_error(ctx, CONSUMERD_ERROR_RECV_FD);
+                       lttng_consumer_send_error(ctx, LTTCOMM_CONSUMERD_ERROR_RECV_FD);
                        rcu_read_unlock();
                        return ret;
                }
@@ -200,7 +206,7 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                                msg.u.stream.net_index,
                                msg.u.stream.metadata_flag);
                if (new_stream == NULL) {
-                       lttng_consumer_send_error(ctx, CONSUMERD_OUTFD_ERROR);
+                       lttng_consumer_send_error(ctx, LTTCOMM_CONSUMERD_OUTFD_ERROR);
                        goto end_nosignal;
                }
 
@@ -223,14 +229,29 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                        goto end_nosignal;
                }
 
-               if (ctx->on_recv_stream != NULL) {
-                       ret = ctx->on_recv_stream(new_stream);
-                       if (ret == 0) {
-                               consumer_add_stream(new_stream);
-                       } else if (ret < 0) {
-                               goto end_nosignal;
+               /* Send stream to the metadata thread */
+               if (new_stream->metadata_flag) {
+                       if (ctx->on_recv_stream) {
+                               ret = ctx->on_recv_stream(new_stream);
+                               if (ret < 0) {
+                                       goto end_nosignal;
+                               }
+                       }
+
+                       do {
+                               ret = write(ctx->consumer_metadata_pipe[1], new_stream,
+                                               sizeof(struct lttng_consumer_stream));
+                       } while (ret < 0 && errno == EINTR);
+                       if (ret < 0) {
+                               PERROR("write metadata pipe");
                        }
                } else {
+                       if (ctx->on_recv_stream) {
+                               ret = ctx->on_recv_stream(new_stream);
+                               if (ret < 0) {
+                                       goto end_nosignal;
+                               }
+                       }
                        consumer_add_stream(new_stream);
                }
 
@@ -305,9 +326,13 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                ret = write(ctx->consumer_poll_pipe[1], "", 1);
        } while (ret < 0 && errno == EINTR);
 end_nosignal:
-       /* XXX: At some point we might want to return something else than zero */
        rcu_read_unlock();
-       return 0;
+
+       /*
+        * Return 1 to indicate success since the 0 value can be a socket
+        * shutdown during the recv() or send() call.
+        */
+       return 1;
 }
 
 int lttng_ustconsumer_allocate_channel(struct lttng_consumer_channel *chan)
@@ -375,7 +400,7 @@ void lttng_ustconsumer_del_stream(struct lttng_consumer_stream *stream)
 int lttng_ustconsumer_read_subbuffer(struct lttng_consumer_stream *stream,
                struct lttng_consumer_local_data *ctx)
 {
-       unsigned long len;
+       unsigned long len, subbuf_size, padding;
        int err;
        long ret = 0;
        struct lttng_ust_shm_handle *handle;
@@ -402,7 +427,7 @@ int lttng_ustconsumer_read_subbuffer(struct lttng_consumer_stream *stream,
        /* Get the next subbuffer */
        err = ustctl_get_next_subbuf(handle, buf);
        if (err != 0) {
-               ret = -ret;     /* ustctl_get_next_subbuf returns negative, caller expect positive. */
+               ret = err;      /* ustctl_get_next_subbuf returns negative, caller expect positive. */
                /*
                 * This is a debug message even for single-threaded consumer,
                 * because poll() have more relaxed criterions than get subbuf,
@@ -414,17 +439,34 @@ int lttng_ustconsumer_read_subbuffer(struct lttng_consumer_stream *stream,
                goto end;
        }
        assert(stream->output == LTTNG_EVENT_MMAP);
-       /* read the used subbuffer size */
+       /* Get the full padded subbuffer size */
        err = ustctl_get_padded_subbuf_size(handle, buf, &len);
        assert(err == 0);
+
+       /* Get subbuffer data size (without padding) */
+       err = ustctl_get_subbuf_size(handle, buf, &subbuf_size);
+       assert(err == 0);
+
+       /* Make sure we don't get a subbuffer size bigger than the padded */
+       assert(len >= subbuf_size);
+
+       padding = len - subbuf_size;
        /* write the subbuffer to the tracefile */
-       ret = lttng_consumer_on_read_subbuffer_mmap(ctx, stream, len);
-       if (ret != len) {
+       ret = lttng_consumer_on_read_subbuffer_mmap(ctx, stream, subbuf_size, padding);
+       /*
+        * The mmap operation should write subbuf_size amount of data when network
+        * streaming or the full padding (len) size when we are _not_ streaming.
+        */
+       if ((ret != subbuf_size && stream->net_seq_idx != -1) ||
+                       (ret != len && stream->net_seq_idx == -1)) {
                /*
-                * display the error but continue processing to try
-                * to release the subbuffer
+                * Display the error but continue processing to try to release the
+                * subbuffer
                 */
-               ERR("Error writing to tracefile (expected: %ld, got: %ld)", ret, len);
+               ERR("Error writing to tracefile "
+                               "(ret: %zd != len: %lu != subbuf_size: %lu)",
+                               ret, len, subbuf_size);
+
        }
        err = ustctl_put_next_subbuf(handle, buf);
        assert(err == 0);
This page took 0.025473 seconds and 4 git commands to generate.