Implement channel fd monitoring thread for UST
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Sat, 9 Mar 2013 16:58:42 +0000 (11:58 -0500)
committerDavid Goulet <dgoulet@efficios.com>
Mon, 11 Mar 2013 14:21:36 +0000 (10:21 -0400)
This new thread uses a new hash table containing channels and monitors
their wait_fd. On hang up, the channel streams are closed but *not*
deleted so the teardown process of channel and streams are untouched.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Signed-off-by: David Goulet <dgoulet@efficios.com>
src/bin/lttng-consumerd/lttng-consumerd.c
src/common/consumer.c
src/common/consumer.h
src/common/kernel-consumer/kernel-consumer.c
src/common/ust-consumer/ust-consumer.c
src/common/ust-consumer/ust-consumer.h

index b854aabac9923c9b832b81b338d933b2feafa6d7..84868077c39e5e85624a973d70bfca270670bce2 100644 (file)
@@ -51,8 +51,8 @@
 
 /* TODO : support UST (all direct kernel-ctl accesses). */
 
-/* the two threads (receive fd, poll and metadata) */
-static pthread_t data_thread, metadata_thread, sessiond_thread;
+/* threads (channel handling, poll, metadata, sessiond) */
+static pthread_t channel_thread, data_thread, metadata_thread, sessiond_thread;
 
 /* to count the number of times the user pressed ctrl+c */
 static int sigintcount = 0;
@@ -363,12 +363,20 @@ int main(int argc, char **argv)
        }
        lttng_consumer_set_error_sock(ctx, ret);
 
+       /* Create thread to manage channels */
+       ret = pthread_create(&channel_thread, NULL, consumer_thread_channel_poll,
+                       (void *) ctx);
+       if (ret != 0) {
+               perror("pthread_create");
+               goto error;
+       }
+
        /* Create thread to manage the polling/writing of trace metadata */
        ret = pthread_create(&metadata_thread, NULL, consumer_thread_metadata_poll,
                        (void *) ctx);
        if (ret != 0) {
                perror("pthread_create");
-               goto error;
+               goto metadata_error;
        }
 
        /* Create thread to manage the polling/writing of trace data */
@@ -407,6 +415,13 @@ data_error:
                goto error;
        }
 
+metadata_error:
+       ret = pthread_join(channel_thread, &status);
+       if (ret != 0) {
+               perror("pthread_join");
+               goto error;
+       }
+
        if (!ret) {
                ret = EXIT_SUCCESS;
                lttng_consumer_send_error(ctx, LTTCOMM_CONSUMERD_EXIT_SUCCESS);
index 25f891af9abf17b3f9e7beb4ed2e75bec671296e..300fd2a2fc896108ac60c43ce920a5f633be111b 100644 (file)
@@ -47,6 +47,16 @@ struct lttng_consumer_global_data consumer_data = {
        .type = LTTNG_CONSUMER_UNKNOWN,
 };
 
+enum consumer_channel_action {
+       CONSUMER_CHANNEL_ADD,
+       CONSUMER_CHANNEL_QUIT,
+};
+
+struct consumer_channel_msg {
+       enum consumer_channel_action action;
+       struct lttng_consumer_channel *chan;
+};
+
 /*
  * Flag to inform the polling thread to quit when all fd hung up. Updated by
  * the consumer_thread_receive_fds when it notices that all fds has hung up.
@@ -78,6 +88,37 @@ static void notify_thread_pipe(int wpipe)
        } while (ret < 0 && errno == EINTR);
 }
 
+static void notify_channel_pipe(struct lttng_consumer_local_data *ctx,
+               struct lttng_consumer_channel *chan,
+               enum consumer_channel_action action)
+{
+       struct consumer_channel_msg msg;
+       int ret;
+
+       msg.action = action;
+       msg.chan = chan;
+       do {
+               ret = write(ctx->consumer_channel_pipe[1], &msg, sizeof(msg));
+       } while (ret < 0 && errno == EINTR);
+}
+
+static int read_channel_pipe(struct lttng_consumer_local_data *ctx,
+               struct lttng_consumer_channel **chan,
+               enum consumer_channel_action *action)
+{
+       struct consumer_channel_msg msg;
+       int ret;
+
+       do {
+               ret = read(ctx->consumer_channel_pipe[0], &msg, sizeof(msg));
+       } while (ret < 0 && errno == EINTR);
+       if (ret > 0) {
+               *action = msg.action;
+               *chan = msg.chan;
+       }
+       return ret;
+}
+
 /*
  * Find a stream. The consumer_data.lock must be locked during this
  * call.
@@ -425,7 +466,10 @@ void consumer_del_stream(struct lttng_consumer_stream *stream,
        ret = lttng_ht_del(ht, &iter);
        assert(!ret);
 
-       /* Remove node session id from the consumer_data stream ht */
+       iter.iter.node = &stream->node_channel_id.node;
+       ret = lttng_ht_del(consumer_data.stream_per_chan_id_ht, &iter);
+       assert(!ret);
+
        iter.iter.node = &stream->node_session_id.node;
        ret = lttng_ht_del(consumer_data.stream_list_ht, &iter);
        assert(!ret);
@@ -542,11 +586,14 @@ struct lttng_consumer_stream *consumer_allocate_stream(uint64_t channel_key,
        /* Key is always the wait_fd for streams. */
        lttng_ht_node_init_u64(&stream->node, stream->key);
 
+       /* Init node per channel id key */
+       lttng_ht_node_init_u64(&stream->node_channel_id, channel_key);
+
        /* Init session id node with the stream session id */
        lttng_ht_node_init_u64(&stream->node_session_id, stream->session_id);
 
-       DBG3("Allocated stream %s (key %" PRIu64 ", relayd_id %" PRIu64 ", session_id %" PRIu64,
-                       stream->name, stream->key, stream->net_seq_idx, stream->session_id);
+       DBG3("Allocated stream %s (key %" PRIu64 ", chan_key %" PRIu64 " relayd_id %" PRIu64 ", session_id %" PRIu64,
+                       stream->name, stream->key, channel_key, stream->net_seq_idx, stream->session_id);
 
        rcu_read_unlock();
        return stream;
@@ -584,6 +631,9 @@ static int add_stream(struct lttng_consumer_stream *stream,
 
        lttng_ht_add_unique_u64(ht, &stream->node);
 
+       lttng_ht_add_u64(consumer_data.stream_per_chan_id_ht,
+                       &stream->node_channel_id);
+
        /*
         * Add stream to the stream_list_ht of the consumer data. No need to steal
         * the key since the HT does not use it and we allow to add redundant keys
@@ -802,6 +852,9 @@ struct lttng_consumer_channel *consumer_allocate_channel(unsigned long key,
        channel->name[sizeof(channel->name) - 1] = '\0';
 
        lttng_ht_node_init_u64(&channel->node, channel->key);
+
+       channel->wait_fd = -1;
+
        CDS_INIT_LIST_HEAD(&channel->streams.head);
 
        DBG("Allocated channel (key %" PRIu64 ")", channel->key)
@@ -813,7 +866,8 @@ end:
 /*
  * Add a channel to the global list protected by a mutex.
  */
-int consumer_add_channel(struct lttng_consumer_channel *channel)
+int consumer_add_channel(struct lttng_consumer_channel *channel,
+               struct lttng_consumer_local_data *ctx)
 {
        int ret = 0;
        struct lttng_ht_node_u64 *node;
@@ -839,6 +893,10 @@ end:
        rcu_read_unlock();
        pthread_mutex_unlock(&consumer_data.lock);
 
+       if (!ret && channel->wait_fd != -1 &&
+                       channel->metadata_stream == NULL) {
+               notify_channel_pipe(ctx, channel, CONSUMER_CHANNEL_ADD);
+       }
        return ret;
 }
 
@@ -979,6 +1037,8 @@ void lttng_consumer_cleanup(void)
 
        cleanup_relayd_ht();
 
+       lttng_ht_destroy(consumer_data.stream_per_chan_id_ht);
+
        /*
         * This HT contains streams that are freed by either the metadata thread or
         * the data thread so we do *nothing* on the hash table and simply destroy
@@ -1063,7 +1123,7 @@ struct lttng_consumer_local_data *lttng_consumer_create(
                int (*recv_stream)(struct lttng_consumer_stream *stream),
                int (*update_stream)(int stream_key, uint32_t state))
 {
-       int ret, i;
+       int ret;
        struct lttng_consumer_local_data *ctx;
 
        assert(consumer_data.type == LTTNG_CONSUMER_UNKNOWN ||
@@ -1115,6 +1175,12 @@ struct lttng_consumer_local_data *lttng_consumer_create(
                goto error_thread_pipe;
        }
 
+       ret = pipe(ctx->consumer_channel_pipe);
+       if (ret < 0) {
+               PERROR("Error creating channel pipe");
+               goto error_channel_pipe;
+       }
+
        ret = utils_create_pipe(ctx->consumer_metadata_pipe);
        if (ret < 0) {
                goto error_metadata_pipe;
@@ -1130,26 +1196,14 @@ struct lttng_consumer_local_data *lttng_consumer_create(
 error_splice_pipe:
        utils_close_pipe(ctx->consumer_metadata_pipe);
 error_metadata_pipe:
+       utils_close_pipe(ctx->consumer_channel_pipe);
+error_channel_pipe:
        utils_close_pipe(ctx->consumer_thread_pipe);
 error_thread_pipe:
-       for (i = 0; i < 2; i++) {
-               int err;
-
-               err = close(ctx->consumer_should_quit[i]);
-               if (err) {
-                       PERROR("close");
-               }
-       }
+       utils_close_pipe(ctx->consumer_should_quit);
 error_poll_fcntl:
 error_quit_pipe:
-       for (i = 0; i < 2; i++) {
-               int err;
-
-               err = close(ctx->consumer_data_pipe[i]);
-               if (err) {
-                       PERROR("close");
-               }
-       }
+       utils_close_pipe(ctx->consumer_data_pipe);
 error_poll_pipe:
        free(ctx);
 error:
@@ -1169,30 +1223,10 @@ void lttng_consumer_destroy(struct lttng_consumer_local_data *ctx)
        if (ret) {
                PERROR("close");
        }
-       ret = close(ctx->consumer_thread_pipe[0]);
-       if (ret) {
-               PERROR("close");
-       }
-       ret = close(ctx->consumer_thread_pipe[1]);
-       if (ret) {
-               PERROR("close");
-       }
-       ret = close(ctx->consumer_data_pipe[0]);
-       if (ret) {
-               PERROR("close");
-       }
-       ret = close(ctx->consumer_data_pipe[1]);
-       if (ret) {
-               PERROR("close");
-       }
-       ret = close(ctx->consumer_should_quit[0]);
-       if (ret) {
-               PERROR("close");
-       }
-       ret = close(ctx->consumer_should_quit[1]);
-       if (ret) {
-               PERROR("close");
-       }
+       utils_close_pipe(ctx->consumer_thread_pipe);
+       utils_close_pipe(ctx->consumer_channel_pipe);
+       utils_close_pipe(ctx->consumer_data_pipe);
+       utils_close_pipe(ctx->consumer_should_quit);
        utils_close_pipe(ctx->consumer_splice_metadata_pipe);
 
        unlink(ctx->consumer_command_sock_path);
@@ -1806,7 +1840,10 @@ void consumer_del_metadata_stream(struct lttng_consumer_stream *stream,
        ret = lttng_ht_del(ht, &iter);
        assert(!ret);
 
-       /* Remove node session id from the consumer_data stream ht */
+       iter.iter.node = &stream->node_channel_id.node;
+       ret = lttng_ht_del(consumer_data.stream_per_chan_id_ht, &iter);
+       assert(!ret);
+
        iter.iter.node = &stream->node_session_id.node;
        ret = lttng_ht_del(consumer_data.stream_list_ht, &iter);
        assert(!ret);
@@ -1925,6 +1962,9 @@ static int add_metadata_stream(struct lttng_consumer_stream *stream,
 
        lttng_ht_add_unique_u64(ht, &stream->node);
 
+       lttng_ht_add_unique_u64(consumer_data.stream_per_chan_id_ht,
+               &stream->node_channel_id);
+
        /*
         * Add stream to the stream_list_ht of the consumer data. No need to steal
         * the key since the HT does not use it and we allow to add redundant keys
@@ -2012,7 +2052,7 @@ void *consumer_thread_metadata_poll(void *data)
        metadata_ht = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
        if (!metadata_ht) {
                /* ENOMEM at this point. Better to bail out. */
-               goto error;
+               goto end_ht;
        }
 
        DBG("Thread metadata poll started");
@@ -2021,7 +2061,7 @@ void *consumer_thread_metadata_poll(void *data)
        ret = lttng_poll_create(&events, 2, LTTNG_CLOEXEC);
        if (ret < 0) {
                ERR("Poll set creation failed");
-               goto end;
+               goto end_poll;
        }
 
        ret = lttng_poll_add(&events, ctx->consumer_metadata_pipe[0], LPOLLIN);
@@ -2180,10 +2220,11 @@ restart:
 error:
 end:
        DBG("Metadata poll thread exiting");
-       lttng_poll_clean(&events);
 
+       lttng_poll_clean(&events);
+end_poll:
        destroy_stream_ht(metadata_ht);
-
+end_ht:
        rcu_unregister_thread();
        return NULL;
 }
@@ -2446,6 +2487,222 @@ end:
        return NULL;
 }
 
+/*
+ * Close wake-up end of each stream belonging to the channel. This will
+ * allow the poll() on the stream read-side to detect when the
+ * write-side (application) finally closes them.
+ */
+static
+void consumer_close_channel_streams(struct lttng_consumer_channel *channel)
+{
+       struct lttng_ht *ht;
+       struct lttng_consumer_stream *stream;
+       struct lttng_ht_iter iter;
+
+       ht = consumer_data.stream_per_chan_id_ht;
+
+       rcu_read_lock();
+       cds_lfht_for_each_entry_duplicate(ht->ht,
+                       ht->hash_fct(&channel->key, lttng_ht_seed),
+                       ht->match_fct, &channel->key,
+                       &iter.iter, stream, node_channel_id.node) {
+               switch (consumer_data.type) {
+               case LTTNG_CONSUMER_KERNEL:
+                       break;
+               case LTTNG_CONSUMER32_UST:
+               case LTTNG_CONSUMER64_UST:
+                       /*
+                        * Note: a mutex is taken internally within
+                        * liblttng-ust-ctl to protect timer wakeup_fd
+                        * use from concurrent close.
+                        */
+                       lttng_ustconsumer_close_stream_wakeup(stream);
+                       break;
+               default:
+                       ERR("Unknown consumer_data type");
+                       assert(0);
+               }
+       }
+       rcu_read_unlock();
+}
+
+static void destroy_channel_ht(struct lttng_ht *ht)
+{
+       struct lttng_ht_iter iter;
+       struct lttng_consumer_channel *channel;
+       int ret;
+
+       if (ht == NULL) {
+               return;
+       }
+
+       rcu_read_lock();
+       cds_lfht_for_each_entry(ht->ht, &iter.iter, channel, wait_fd_node.node) {
+               ret = lttng_ht_del(ht, &iter);
+               assert(ret != 0);
+       }
+       rcu_read_unlock();
+
+       lttng_ht_destroy(ht);
+}
+
+/*
+ * This thread polls the channel fds to detect when they are being
+ * closed. It closes all related streams if the channel is detected as
+ * closed. It is currently only used as a shim layer for UST because the
+ * consumerd needs to keep the per-stream wakeup end of pipes open for
+ * periodical flush.
+ */
+void *consumer_thread_channel_poll(void *data)
+{
+       int ret, i, pollfd;
+       uint32_t revents, nb_fd;
+       struct lttng_consumer_channel *chan = NULL;
+       struct lttng_ht_iter iter;
+       struct lttng_ht_node_u64 *node;
+       struct lttng_poll_event events;
+       struct lttng_consumer_local_data *ctx = data;
+       struct lttng_ht *channel_ht;
+
+       rcu_register_thread();
+
+       channel_ht = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
+       if (!channel_ht) {
+               /* ENOMEM at this point. Better to bail out. */
+               goto end_ht;
+       }
+
+       DBG("Thread channel poll started");
+
+       /* Size is set to 1 for the consumer_channel pipe */
+       ret = lttng_poll_create(&events, 2, LTTNG_CLOEXEC);
+       if (ret < 0) {
+               ERR("Poll set creation failed");
+               goto end_poll;
+       }
+
+       ret = lttng_poll_add(&events, ctx->consumer_channel_pipe[0], LPOLLIN);
+       if (ret < 0) {
+               goto end;
+       }
+
+       /* Main loop */
+       DBG("Channel main loop started");
+
+       while (1) {
+               /* Only the channel pipe is set */
+               if (LTTNG_POLL_GETNB(&events) == 0 && consumer_quit == 1) {
+                       goto end;
+               }
+
+restart:
+               DBG("Channel poll wait with %d fd(s)", LTTNG_POLL_GETNB(&events));
+               ret = lttng_poll_wait(&events, -1);
+               DBG("Channel event catched in thread");
+               if (ret < 0) {
+                       if (errno == EINTR) {
+                               ERR("Poll EINTR catched");
+                               goto restart;
+                       }
+                       goto end;
+               }
+
+               nb_fd = ret;
+
+               /* From here, the event is a channel wait fd */
+               for (i = 0; i < nb_fd; i++) {
+                       revents = LTTNG_POLL_GETEV(&events, i);
+                       pollfd = LTTNG_POLL_GETFD(&events, i);
+
+                       /* Just don't waste time if no returned events for the fd */
+                       if (!revents) {
+                               continue;
+                       }
+                       if (pollfd == ctx->consumer_channel_pipe[0]) {
+                               if (revents & (LPOLLERR | LPOLLHUP)) {
+                                       DBG("Channel thread pipe hung up");
+                                       /*
+                                        * Remove the pipe from the poll set and continue the loop
+                                        * since their might be data to consume.
+                                        */
+                                       lttng_poll_del(&events, ctx->consumer_channel_pipe[0]);
+                                       continue;
+                               } else if (revents & LPOLLIN) {
+                                       enum consumer_channel_action action;
+
+                                       ret = read_channel_pipe(ctx, &chan, &action);
+                                       if (ret <= 0) {
+                                               ERR("Error reading channel pipe");
+                                               continue;
+                                       }
+
+                                       switch (action) {
+                                       case CONSUMER_CHANNEL_ADD:
+                                               DBG("Adding channel %d to poll set",
+                                                       chan->wait_fd);
+
+                                               lttng_ht_node_init_u64(&chan->wait_fd_node,
+                                                       chan->wait_fd);
+                                               lttng_ht_add_unique_u64(channel_ht,
+                                                               &chan->wait_fd_node);
+                                               /* Add channel to the global poll events list */
+                                               lttng_poll_add(&events, chan->wait_fd,
+                                                               LPOLLIN | LPOLLPRI);
+                                               break;
+                                       case CONSUMER_CHANNEL_QUIT:
+                                               /*
+                                                * Remove the pipe from the poll set and continue the loop
+                                                * since their might be data to consume.
+                                                */
+                                               lttng_poll_del(&events, ctx->consumer_channel_pipe[0]);
+                                               continue;
+                                       default:
+                                               ERR("Unknown action");
+                                               break;
+                                       }
+                               }
+
+                               /* Handle other stream */
+                               continue;
+                       }
+
+                       rcu_read_lock();
+                       {
+                               uint64_t tmp_id = (uint64_t) pollfd;
+
+                               lttng_ht_lookup(channel_ht, &tmp_id, &iter);
+                       }
+                       node = lttng_ht_iter_get_node_u64(&iter);
+                       assert(node);
+
+                       chan = caa_container_of(node, struct lttng_consumer_channel,
+                                       wait_fd_node);
+
+                       /* Check for error event */
+                       if (revents & (LPOLLERR | LPOLLHUP)) {
+                               DBG("Channel fd %d is hup|err.", pollfd);
+
+                               lttng_poll_del(&events, chan->wait_fd);
+                               ret = lttng_ht_del(channel_ht, &iter);
+                               assert(ret == 0);
+                               consumer_close_channel_streams(chan);
+                       }
+
+                       /* Release RCU lock for the channel looked up */
+                       rcu_read_unlock();
+               }
+       }
+
+end:
+       lttng_poll_clean(&events);
+end_poll:
+       destroy_channel_ht(channel_ht);
+end_ht:
+       DBG("Channel poll thread exiting");
+       rcu_unregister_thread();
+       return NULL;
+}
+
 /*
  * This thread listens on the consumerd socket and receives the file
  * descriptors from the session daemon.
@@ -2570,6 +2827,8 @@ end:
         */
        notify_thread_pipe(ctx->consumer_data_pipe[1]);
 
+       notify_channel_pipe(ctx, NULL, CONSUMER_CHANNEL_QUIT);
+
        /* Cleaning up possibly open sockets. */
        if (sock >= 0) {
                ret = close(sock);
@@ -2637,6 +2896,7 @@ void lttng_consumer_init(void)
        consumer_data.channel_ht = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
        consumer_data.relayd_ht = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
        consumer_data.stream_list_ht = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
+       consumer_data.stream_per_chan_id_ht = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
 }
 
 /*
index a3e1ec3535094f169042d1bd70dae73fc19d5f58..29836e5b09cf6e25220e20baac2d3fd48b5cfa08 100644 (file)
@@ -136,6 +136,11 @@ struct lttng_consumer_channel {
         * contiguousness and order.
         */
        uint64_t contig_metadata_written;
+
+       /* for UST */
+       int wait_fd;
+       /* Node within channel thread ht */
+       struct lttng_ht_node_u64 wait_fd_node;
 };
 
 /*
@@ -145,6 +150,8 @@ struct lttng_consumer_channel {
 struct lttng_consumer_stream {
        /* HT node used by the data_ht and metadata_ht */
        struct lttng_ht_node_u64 node;
+       /* stream indexed per channel key node */
+       struct lttng_ht_node_u64 node_channel_id;
        /* HT node used in consumer_data.stream_list_ht */
        struct lttng_ht_node_u64 node_session_id;
        /* Pointer to associated channel. */
@@ -320,6 +327,7 @@ struct lttng_consumer_local_data {
        char *consumer_command_sock_path;
        /* communication with splice */
        int consumer_thread_pipe[2];
+       int consumer_channel_pipe[2];
        int consumer_splice_metadata_pipe[2];
        /* Data stream poll thread pipe. To transfer data stream to the thread */
        int consumer_data_pipe[2];
@@ -372,6 +380,11 @@ struct lttng_consumer_global_data {
         * This HT uses the "node_session_id" of the consumer stream.
         */
        struct lttng_ht *stream_list_ht;
+
+       /*
+        * This HT uses the "node_channel_id" of the consumer stream.
+        */
+       struct lttng_ht *stream_per_chan_id_ht;
 };
 
 /*
@@ -444,7 +457,8 @@ void consumer_del_stream(struct lttng_consumer_stream *stream,
                struct lttng_ht *ht);
 void consumer_del_metadata_stream(struct lttng_consumer_stream *stream,
                struct lttng_ht *ht);
-int consumer_add_channel(struct lttng_consumer_channel *channel);
+int consumer_add_channel(struct lttng_consumer_channel *channel,
+               struct lttng_consumer_local_data *ctx);
 void consumer_del_channel(struct lttng_consumer_channel *channel);
 
 /* lttng-relayd consumer command */
@@ -478,6 +492,7 @@ int lttng_consumer_get_produced_snapshot(struct lttng_consumer_stream *stream,
 void *consumer_thread_metadata_poll(void *data);
 void *consumer_thread_data_poll(void *data);
 void *consumer_thread_sessiond_poll(void *data);
+void *consumer_thread_channel_poll(void *data);
 int lttng_consumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                int sock, struct pollfd *consumer_sockpoll);
 
index ca1e98be1f359dc08dfba8a41d3c61832ad23d9f..0de73443e1bee5c51549e608d20b1548cb007257 100644 (file)
@@ -153,12 +153,12 @@ int lttng_kconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                if (ctx->on_recv_channel != NULL) {
                        ret = ctx->on_recv_channel(new_channel);
                        if (ret == 0) {
-                               consumer_add_channel(new_channel);
+                               consumer_add_channel(new_channel, ctx);
                        } else if (ret < 0) {
                                goto end_nosignal;
                        }
                } else {
-                       consumer_add_channel(new_channel);
+                       consumer_add_channel(new_channel, ctx);
                }
                goto end_nosignal;
        }
index 5d9dc96c7925fd61d1efa44f43637e31df79b9e1..5a09ff51fb751069a3ad2fdbed17e698a0630dd0 100644 (file)
@@ -88,14 +88,14 @@ static int add_channel(struct lttng_consumer_channel *channel,
        if (ctx->on_recv_channel != NULL) {
                ret = ctx->on_recv_channel(channel);
                if (ret == 0) {
-                       ret = consumer_add_channel(channel);
+                       ret = consumer_add_channel(channel, ctx);
                } else if (ret < 0) {
                        /* Most likely an ENOMEM. */
                        lttng_consumer_send_error(ctx, LTTCOMM_CONSUMERD_OUTFD_ERROR);
                        goto error;
                }
        } else {
-               ret = consumer_add_channel(channel);
+               ret = consumer_add_channel(channel, ctx);
        }
 
        DBG("UST consumer channel added (key: %" PRIu64 ")", channel->key);
@@ -368,11 +368,6 @@ static int send_sessiond_stream(int sock, struct lttng_consumer_stream *stream)
                goto error;
        }
 
-       ret = ustctl_stream_close_wakeup_fd(stream->ustream);
-       if (ret < 0) {
-               goto error;
-       }
-
 error:
        return ret;
 }
@@ -401,6 +396,11 @@ static int send_sessiond_channel(int sock,
                goto error;
        }
 
+       ret = ustctl_channel_close_wakeup_fd(channel->uchan);
+       if (ret < 0) {
+               goto error;
+       }
+
        /* The channel was sent successfully to the sessiond at this point. */
        cds_list_for_each_entry(stream, &channel->streams.head, send_node) {
                /* Try to send the stream to the relayd if one is available. */
@@ -476,6 +476,12 @@ static int ask_channel(struct lttng_consumer_local_data *ctx, int sock,
                goto error;
        }
 
+       channel->wait_fd = ustctl_channel_get_wait_fd(channel->uchan);
+
+       if (ret < 0) {
+               goto error;
+       }
+
        /* Open all streams for this channel. */
        ret = create_ust_streams(channel, ctx);
        if (ret < 0) {
@@ -1277,3 +1283,13 @@ void lttng_ustconsumer_close_metadata(struct lttng_ht *metadata_ht)
        }
        rcu_read_unlock();
 }
+
+void lttng_ustconsumer_close_stream_wakeup(struct lttng_consumer_stream *stream)
+{
+       int ret;
+
+       ret = ustctl_stream_close_wakeup_fd(stream->ustream);
+       if (ret < 0) {
+               ERR("Unable to close wakeup fd");
+       }
+}
index 2c3c0e8703427fba29c37695d7e7d6b02c6b493f..bbaff6cbf4dbcd3c667477b363f1feb1bcd2914b 100644 (file)
@@ -50,6 +50,7 @@ int lttng_ustctl_get_mmap_read_offset(struct lttng_consumer_stream *stream,
 void *lttng_ustctl_get_mmap_base(struct lttng_consumer_stream *stream);
 int lttng_ustconsumer_data_pending(struct lttng_consumer_stream *stream);
 void lttng_ustconsumer_close_metadata(struct lttng_ht *ht);
+void lttng_ustconsumer_close_stream_wakeup(struct lttng_consumer_stream *stream);
 
 #else /* HAVE_LIBLTTNG_UST_CTL */
 
@@ -151,6 +152,10 @@ static inline
 void lttng_ustconsumer_close_metadata(struct lttng_ht *ht)
 {
 }
+static inline
+void lttng_ustconsumer_close_stream_wakeup(struct lttng_consumer_stream *stream)
+{
+}
 #endif /* HAVE_LIBLTTNG_UST_CTL */
 
 #endif /* _LTTNG_USTCONSUMER_H */
This page took 0.036951 seconds and 4 git commands to generate.