Fix: don't send error to sessiond on orderly shutdown
[lttng-tools.git] / src / common / ust-consumer / ust-consumer.c
index f783d4058c550033983045c93cbeddcc363028d3..9550ef424d93877acac1e8e33411739b2c820b5c 100644 (file)
@@ -113,14 +113,16 @@ error:
  */
 static struct lttng_consumer_channel *allocate_channel(uint64_t session_id,
                const char *pathname, const char *name, uid_t uid, gid_t gid,
-               int relayd_id, uint64_t key, enum lttng_event_output output,
-               uint64_t tracefile_size, uint64_t tracefile_count)
+               uint64_t relayd_id, uint64_t key, enum lttng_event_output output,
+               uint64_t tracefile_size, uint64_t tracefile_count,
+               uint64_t session_id_per_pid)
 {
        assert(pathname);
        assert(name);
 
-       return consumer_allocate_channel(key, session_id, pathname, name, uid, gid,
-                       relayd_id, output, tracefile_size, tracefile_count);
+       return consumer_allocate_channel(key, session_id, pathname, name, uid,
+                       gid, relayd_id, output, tracefile_size,
+                       tracefile_count, session_id_per_pid);
 }
 
 /*
@@ -373,7 +375,7 @@ static int send_sessiond_stream(int sock, struct lttng_consumer_stream *stream)
        assert(stream);
        assert(sock >= 0);
 
-       DBG2("UST consumer sending stream %" PRIu64 " to sessiond", stream->key);
+       DBG("UST consumer sending stream %" PRIu64 " to sessiond", stream->key);
 
        /* Send stream to session daemon. */
        ret = ustctl_send_stream_to_sessiond(sock, stream->ustream);
@@ -651,6 +653,7 @@ static int close_metadata(uint64_t chan_key)
        }
 
        pthread_mutex_lock(&consumer_data.lock);
+       pthread_mutex_lock(&channel->lock);
 
        if (cds_lfht_is_node_deleted(&channel->node.node)) {
                goto error_unlock;
@@ -671,6 +674,7 @@ static int close_metadata(uint64_t chan_key)
        }
 
 error_unlock:
+       pthread_mutex_unlock(&channel->lock);
        pthread_mutex_unlock(&consumer_data.lock);
 error:
        return ret;
@@ -742,7 +746,8 @@ error_find:
  * Receive the metadata updates from the sessiond.
  */
 int lttng_ustconsumer_recv_metadata(int sock, uint64_t key, uint64_t offset,
-               uint64_t len, struct lttng_consumer_channel *channel)
+               uint64_t len, struct lttng_consumer_channel *channel,
+               int timer)
 {
        int ret, ret_code = LTTNG_OK;
        char *metadata_str;
@@ -764,17 +769,10 @@ int lttng_ustconsumer_recv_metadata(int sock, uint64_t key, uint64_t offset,
                goto end_free;
        }
 
-       /*
-        * XXX: The consumer data lock is acquired before calling metadata cache
-        * write which calls push metadata that MUST be protected by the consumer
-        * lock in order to be able to check the validity of the metadata stream of
-        * the channel.
-        *
-        * Note that this will be subject to change to better fine grained locking
-        * and ultimately try to get rid of this global consumer data lock.
-        */
-       pthread_mutex_lock(&consumer_data.lock);
-
+       if (!timer) {
+               pthread_mutex_lock(&channel->lock);
+       }
+       pthread_mutex_lock(&channel->timer_lock);
        pthread_mutex_lock(&channel->metadata_cache->lock);
        ret = consumer_metadata_cache_write(channel, offset, len, metadata_str);
        if (ret < 0) {
@@ -786,13 +784,19 @@ int lttng_ustconsumer_recv_metadata(int sock, uint64_t key, uint64_t offset,
                 * waiting for the metadata cache to be flushed.
                 */
                pthread_mutex_unlock(&channel->metadata_cache->lock);
-               pthread_mutex_unlock(&consumer_data.lock);
+               pthread_mutex_unlock(&channel->timer_lock);
+               if (!timer) {
+                       pthread_mutex_unlock(&channel->lock);
+               }
                goto end_free;
        }
        pthread_mutex_unlock(&channel->metadata_cache->lock);
-       pthread_mutex_unlock(&consumer_data.lock);
+       pthread_mutex_unlock(&channel->timer_lock);
+       if (!timer) {
+               pthread_mutex_unlock(&channel->lock);
+       }
 
-       while (consumer_metadata_cache_flushed(channel, offset + len)) {
+       while (consumer_metadata_cache_flushed(channel, offset + len, timer)) {
                DBG("Waiting for metadata to be flushed");
                usleep(DEFAULT_METADATA_AVAILABILITY_WAIT_TIME);
        }
@@ -820,12 +824,12 @@ 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, LTTCOMM_CONSUMERD_ERROR_RECV_CMD);
                /*
                 * The ret value might 0 meaning an orderly shutdown but this is ok
                 * since the caller handles this.
                 */
                if (ret > 0) {
+                       lttng_consumer_send_error(ctx, LTTCOMM_CONSUMERD_ERROR_RECV_CMD);
                        ret = -1;
                }
                return ret;
@@ -924,7 +928,8 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                                msg.u.ask_channel.relayd_id, msg.u.ask_channel.key,
                                (enum lttng_event_output) msg.u.ask_channel.output,
                                msg.u.ask_channel.tracefile_size,
-                               msg.u.ask_channel.tracefile_count);
+                               msg.u.ask_channel.tracefile_count,
+                               msg.u.ask_channel.session_id_per_pid);
                if (!channel) {
                        goto end_channel_error;
                }
@@ -1127,7 +1132,7 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                }
 
                ret = lttng_ustconsumer_recv_metadata(sock, key, offset,
-                               len, channel);
+                               len, channel, 0);
                if (ret < 0) {
                        /* error receiving from sessiond */
                        goto error_fatal;
@@ -1294,7 +1299,7 @@ int lttng_ustconsumer_read_subbuffer(struct lttng_consumer_stream *stream,
        assert(stream->ustream);
        assert(ctx);
 
-       DBG2("In UST read_subbuffer (wait_fd: %d, name: %s)", stream->wait_fd,
+       DBG("In UST read_subbuffer (wait_fd: %d, name: %s)", stream->wait_fd,
                        stream->name);
 
        /* Ease our life for what's next. */
@@ -1410,6 +1415,11 @@ int lttng_ustconsumer_data_pending(struct lttng_consumer_stream *stream)
 
        DBG("UST consumer checking data pending");
 
+       if (stream->endpoint_status != CONSUMER_ENDPOINT_ACTIVE) {
+               ret = 0;
+               goto end;
+       }
+
        ret = ustctl_get_next_subbuf(stream->ustream);
        if (ret == 0) {
                /* There is still data so let's put back this subbuffer. */
@@ -1474,8 +1484,14 @@ void lttng_ustconsumer_close_stream_wakeup(struct lttng_consumer_stream *stream)
        }
 }
 
+/*
+ * Please refer to consumer-timer.c before adding any lock within this
+ * function or any of its callees. Timers have a very strict locking
+ * semantic with respect to teardown. Failure to respect this semantic
+ * introduces deadlocks.
+ */
 int lttng_ustconsumer_request_metadata(struct lttng_consumer_local_data *ctx,
-               struct lttng_consumer_channel *channel)
+               struct lttng_consumer_channel *channel, int timer)
 {
        struct lttcomm_metadata_request_msg request;
        struct lttcomm_consumer_msg msg;
@@ -1500,10 +1516,13 @@ int lttng_ustconsumer_request_metadata(struct lttng_consumer_local_data *ctx,
        }
 
        request.session_id = channel->session_id;
+       request.session_id_per_pid = channel->session_id_per_pid;
        request.uid = channel->uid;
        request.key = channel->key;
-       DBG("Sending metadata request to sessiond, session %" PRIu64,
-                       channel->session_id);
+       DBG("Sending metadata request to sessiond, session id %" PRIu64
+                       ", per-pid %" PRIu64,
+                       channel->session_id,
+                       channel->session_id_per_pid);
 
        ret = lttcomm_send_unix_sock(ctx->consumer_metadata_socket, &request,
                        sizeof(request));
@@ -1559,7 +1578,7 @@ int lttng_ustconsumer_request_metadata(struct lttng_consumer_local_data *ctx,
        }
 
        ret_code = lttng_ustconsumer_recv_metadata(ctx->consumer_metadata_socket,
-                       key, offset, len, channel);
+                       key, offset, len, channel, timer);
        if (ret_code >= 0) {
                /*
                 * Only send the status msg if the sessiond is alive meaning a positive
This page took 0.0302 seconds and 4 git commands to generate.