Fix: Metadata stream leak when received in consumer
[lttng-tools.git] / src / common / kernel-consumer / kernel-consumer.c
index cd814b8a7f92d5e482d1fd142fb3a6d2dbb68e8c..4d61cc506f32e57896b96bf72ee50b91cc3a50b5 100644 (file)
@@ -118,7 +118,8 @@ int lttng_kconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                new_channel = consumer_allocate_channel(msg.u.channel.channel_key,
                                -1, -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, LTTCOMM_CONSUMERD_OUTFD_ERROR);
                        goto end_nosignal;
@@ -140,6 +141,7 @@ int lttng_kconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                int fd;
                struct consumer_relayd_sock_pair *relayd = NULL;
                struct lttng_consumer_stream *new_stream;
+               int alloc_ret = 0;
 
                /* block */
                if (lttng_consumer_poll_socket(consumer_sockpoll) < 0) {
@@ -165,9 +167,23 @@ int lttng_kconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                                msg.u.stream.uid,
                                msg.u.stream.gid,
                                msg.u.stream.net_index,
-                               msg.u.stream.metadata_flag);
+                               msg.u.stream.metadata_flag,
+                               &alloc_ret);
                if (new_stream == NULL) {
-                       lttng_consumer_send_error(ctx, LTTCOMM_CONSUMERD_OUTFD_ERROR);
+                       switch (alloc_ret) {
+                       case -ENOMEM:
+                       case -EINVAL:
+                       default:
+                               lttng_consumer_send_error(ctx, LTTCOMM_CONSUMERD_OUTFD_ERROR);
+                               break;
+                       case -ENOENT:
+                               /*
+                                * We could not find the channel. Can happen if cpu hotplug
+                                * happens while tearing down.
+                                */
+                               DBG3("Could not find channel");
+                               break;
+                       }
                        goto end_nosignal;
                }
 
@@ -199,29 +215,23 @@ int lttng_kconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                        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;
-                               }
+               if (ctx->on_recv_stream) {
+                       ret = ctx->on_recv_stream(new_stream);
+                       if (ret < 0) {
+                               goto end_nosignal;
                        }
+               }
 
+               /* Send stream to the metadata thread */
+               if (new_stream->metadata_flag) {
                        do {
-                               ret = write(ctx->consumer_metadata_pipe[1], new_stream,
-                                               sizeof(struct lttng_consumer_stream));
+                               ret = write(ctx->consumer_metadata_pipe[1], &new_stream,
+                                               sizeof(new_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);
                }
 
@@ -337,8 +347,12 @@ ssize_t lttng_kconsumer_read_subbuffer(struct lttng_consumer_stream *stream,
                padding = 0;
 
                /* splice the subbuffer to the tracefile */
-               ret = lttng_consumer_on_read_subbuffer_splice(ctx, stream,
-                               subbuf_size, padding);
+               ret = lttng_consumer_on_read_subbuffer_splice(ctx, stream, subbuf_size,
+                               padding);
+               /*
+                * XXX: Splice does not support network streaming so the return value
+                * is simply checked against subbuf_size and not like the mmap() op.
+                */
                if (ret != subbuf_size) {
                        /*
                         * display the error but continue processing to try
@@ -364,15 +378,22 @@ ssize_t lttng_kconsumer_read_subbuffer(struct lttng_consumer_stream *stream,
                padding = len - subbuf_size;
 
                /* write the subbuffer to the tracefile */
-               ret = lttng_consumer_on_read_subbuffer_mmap(ctx, stream,
-                               subbuf_size, padding);
-               if (ret != subbuf_size) {
+               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 (ret: %zd != len: %lu",
-                                       ret, subbuf_size);
+                       ERR("Error writing to tracefile "
+                                       "(ret: %zd != len: %lu != subbuf_size: %lu)",
+                                       ret, len, subbuf_size);
                }
                break;
        default:
This page took 0.024996 seconds and 4 git commands to generate.