[lttng-dev] [PATCH lttng-tools] Fix: consumerd: order of metadata cache vs stream lock

Mathieu Desnoyers mathieu.desnoyers at efficios.com
Mon Jan 9 16:23:16 UTC 2017


The locking order comment in consumer.h is incorrect. First, its
description of locking order is not in sync with the comment found in
consumer-metadata-cache.h. The comment in struct consumer_metadata_cache
only states that the metadata cache lock nests inside the consumer_data
lock, and does not mention the stream lock, which implies that the
metadata cache lock does NOT nest inside the stream lock. But let's
investigate further to confirm:

* lttng_consumer_read_subbuffer() acquires the stream lock, and then
  calls lttng_ustconsumer_read_subbuffer() with stream lock held,
  and then invokes commin_one_metadata_packet(), which acquires the
  metadata cache lock.

* lttng_ustconsumer_sync_metadata() acquires the metadata stream lock,
  and calls commit_one_metadata_packet(), which takes the metadata cache
  lock.

Therefore, update the comment in consumer.h to state that the metadata
cache lock nests INSIDE the stream lock, and update
consumer_del_metadata_stream() accordingly.

This should take care of fixing the locking order reversal found by
Coverity.

CID 1368314 (#1 of 1): Thread deadlock (ORDER_REVERSAL)
CID 1368319:  Program hangs  (ORDER_REVERSAL)

Fixes: 5feafd4130 "Fix: protect the channel's metadata stream using the metadata cache lock"
Fixes: 1ea6cc572b "Fix: lock nesting order reversed"
Fixes: fb549e7ac2 "Fix: reverse channel and metadata cache lock nesting order"
Reported-by: Coverity Scan
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers at efficios.com>
---
 src/common/consumer/consumer.c | 4 ++--
 src/common/consumer/consumer.h | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/common/consumer/consumer.c b/src/common/consumer/consumer.c
index 89dad59..e379171 100644
--- a/src/common/consumer/consumer.c
+++ b/src/common/consumer/consumer.c
@@ -2052,11 +2052,11 @@ void consumer_del_metadata_stream(struct lttng_consumer_stream *stream,
 
 	pthread_mutex_lock(&consumer_data.lock);
 	pthread_mutex_lock(&stream->chan->lock);
+	pthread_mutex_lock(&stream->lock);
 	if (stream->chan->metadata_cache) {
 		/* Only applicable to userspace consumers. */
 		pthread_mutex_lock(&stream->chan->metadata_cache->lock);
 	}
-	pthread_mutex_lock(&stream->lock);
 
 	/* Remove any reference to that stream. */
 	consumer_stream_delete(stream, ht);
@@ -2080,10 +2080,10 @@ void consumer_del_metadata_stream(struct lttng_consumer_stream *stream,
 	 */
 	stream->chan->metadata_stream = NULL;
 
-	pthread_mutex_unlock(&stream->lock);
 	if (stream->chan->metadata_cache) {
 		pthread_mutex_unlock(&stream->chan->metadata_cache->lock);
 	}
+	pthread_mutex_unlock(&stream->lock);
 	pthread_mutex_unlock(&stream->chan->lock);
 	pthread_mutex_unlock(&consumer_data.lock);
 
diff --git a/src/common/consumer/consumer.h b/src/common/consumer/consumer.h
index acefacb..37adecb 100644
--- a/src/common/consumer/consumer.h
+++ b/src/common/consumer/consumer.h
@@ -337,9 +337,9 @@ struct lttng_consumer_stream {
 	 * Lock to use the stream FDs since they are used between threads.
 	 *
 	 * This is nested INSIDE the consumer_data lock.
-	 * This is nested INSIDE the metadata cache lock.
 	 * This is nested INSIDE the channel lock.
 	 * This is nested INSIDE the channel timer lock.
+	 * This is nested OUTSIDE the metadata cache lock.
 	 * This is nested OUTSIDE consumer_relayd_sock_pair lock.
 	 */
 	pthread_mutex_t lock;
-- 
2.1.4



More information about the lttng-dev mailing list