X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=liblttng-consumer%2Flttng-consumer.c;h=293d5f808ea0d2f68d441554563b239911fd02b8;hb=7ad0a0cb283d4004cf9274df8eec4e3530864fc7;hp=7644eac2cefccb7d223c8310c81f7289864f4461;hpb=d41f73b7cb50d57974bd1fad22342abaf9718566;p=lttng-tools.git diff --git a/liblttng-consumer/lttng-consumer.c b/liblttng-consumer/lttng-consumer.c index 7644eac2c..293d5f808 100644 --- a/liblttng-consumer/lttng-consumer.c +++ b/liblttng-consumer/lttng-consumer.c @@ -63,6 +63,9 @@ static struct lttng_consumer_stream *consumer_find_stream(int key) { struct lttng_consumer_stream *iter; + /* Negative keys are lookup failures */ + if (key < 0) + return NULL; cds_list_for_each_entry(iter, &consumer_data.stream_list.head, list) { if (iter->key == key) { DBG("Found stream key %d", key); @@ -72,10 +75,22 @@ static struct lttng_consumer_stream *consumer_find_stream(int key) return NULL; } +static void consumer_steal_stream_key(int key) +{ + struct lttng_consumer_stream *stream; + + stream = consumer_find_stream(key); + if (stream) + stream->key = -1; +} + static struct lttng_consumer_channel *consumer_find_channel(int key) { struct lttng_consumer_channel *iter; + /* Negative keys are lookup failures */ + if (key < 0) + return NULL; cds_list_for_each_entry(iter, &consumer_data.channel_list.head, list) { if (iter->key == key) { DBG("Found channel key %d", key); @@ -85,6 +100,15 @@ static struct lttng_consumer_channel *consumer_find_channel(int key) return NULL; } +static void consumer_steal_channel_key(int key) +{ + struct lttng_consumer_channel *channel; + + channel = consumer_find_channel(key); + if (channel) + channel->key = -1; +} + /* * Remove a stream from the global list protected by a mutex. This * function is also responsible for freeing its data structures. @@ -211,11 +235,8 @@ int consumer_add_stream(struct lttng_consumer_stream *stream) int ret = 0; pthread_mutex_lock(&consumer_data.lock); - /* Check if already exist */ - if (consumer_find_stream(stream->key)) { - ret = -1; - goto end; - } + /* Steal stream identifier, for UST */ + consumer_steal_stream_key(stream->key); cds_list_add(&stream->list, &consumer_data.stream_list.head); consumer_data.stream_count++; consumer_data.need_update = 1; @@ -305,7 +326,7 @@ struct lttng_consumer_channel *consumer_allocate_channel( struct lttng_consumer_channel *channel; int ret; - channel = malloc(sizeof(*channel)); + channel = zmalloc(sizeof(*channel)); if (channel == NULL) { perror("malloc struct lttng_consumer_channel"); goto end; @@ -350,18 +371,12 @@ end: */ int consumer_add_channel(struct lttng_consumer_channel *channel) { - int ret = 0; - pthread_mutex_lock(&consumer_data.lock); - /* Check if already exist */ - if (consumer_find_channel(channel->key)) { - ret = -1; - goto end; - } + /* Steal channel identifier, for UST */ + consumer_steal_channel_key(channel->key); cds_list_add(&channel->list, &consumer_data.channel_list.head); -end: pthread_mutex_unlock(&consumer_data.lock); - return ret; + return 0; } /* @@ -845,9 +860,23 @@ void *lttng_consumer_thread_poll_fds(void *data) ERR("Polling fd %d tells fd is not open.", pollfd[i].fd); consumer_del_stream(local_stream[i]); num_hup++; - } else if ((pollfd[i].revents & POLLHUP && - !(pollfd[i].revents & POLLIN))) { - DBG("Polling fd %d tells it has hung up.", pollfd[i].fd); + } else if ((pollfd[i].revents & POLLHUP) && + !(pollfd[i].revents & POLLIN)) { + if (consumer_data.type == LTTNG_CONSUMER_UST) { + DBG("Polling fd %d tells it has hung up. Attempting flush and read.", + pollfd[i].fd); + if (!local_stream[i]->hangup_flush_done) { + lttng_ustconsumer_on_stream_hangup(local_stream[i]); + /* try reading after flush */ + ret = ctx->on_buffer_ready(local_stream[i], ctx); + /* it's ok to have an unavailable sub-buffer */ + if (ret == EAGAIN) { + ret = 0; + } + } + } else { + DBG("Polling fd %d tells it has hung up.", pollfd[i].fd); + } consumer_del_stream(local_stream[i]); num_hup++; }