Fix: fd leak when closing metadata stream
[lttng-tools.git] / src / common / ust-consumer / ust-consumer.c
index bdabb5e49fcda0e44d6c65018efc0b4f296c6730..34344f4518eeff43b6bd73675bf906635f0531b5 100644 (file)
@@ -629,45 +629,6 @@ error:
        rcu_read_unlock();
        return ret;
 }
-/*
- * Close metadata stream wakeup_fd using the given key to retrieve the channel.
- * RCU read side lock MUST be acquired before calling this function.
- *
- * NOTE: This function does NOT take any channel nor stream lock.
- *
- * Return 0 on success else LTTng error code.
- */
-static int _close_metadata(struct lttng_consumer_channel *channel)
-{
-       int ret = LTTCOMM_CONSUMERD_SUCCESS;
-
-       assert(channel);
-       assert(channel->type == CONSUMER_CHANNEL_TYPE_METADATA);
-
-       if (channel->switch_timer_enabled == 1) {
-               DBG("Deleting timer on metadata channel");
-               consumer_timer_switch_stop(channel);
-       }
-
-       if (channel->metadata_stream) {
-               ret = ustctl_stream_close_wakeup_fd(channel->metadata_stream->ustream);
-               if (ret < 0) {
-                       ERR("UST consumer unable to close fd of metadata (ret: %d)", ret);
-                       ret = LTTCOMM_CONSUMERD_ERROR_METADATA;
-               }
-
-               if (channel->monitor) {
-                       /* Close the read-side in consumer_del_metadata_stream */
-                       ret = close(channel->metadata_stream->ust_metadata_poll_pipe[1]);
-                       if (ret < 0) {
-                               PERROR("Close UST metadata write-side poll pipe");
-                               ret = LTTCOMM_CONSUMERD_ERROR_METADATA;
-                       }
-               }
-       }
-
-       return ret;
-}
 
 /*
  * Close metadata stream wakeup_fd using the given key to retrieve the channel.
@@ -702,7 +663,7 @@ static int close_metadata(uint64_t chan_key)
                goto error_unlock;
        }
 
-       ret = _close_metadata(channel);
+       lttng_ustconsumer_close_metadata(channel);
 
 error_unlock:
        pthread_mutex_unlock(&channel->lock);
@@ -1729,6 +1690,22 @@ void lttng_ustconsumer_del_stream(struct lttng_consumer_stream *stream)
        ustctl_destroy_stream(stream->ustream);
 }
 
+int lttng_ustconsumer_get_wakeup_fd(struct lttng_consumer_stream *stream)
+{
+       assert(stream);
+       assert(stream->ustream);
+
+       return ustctl_stream_get_wakeup_fd(stream->ustream);
+}
+
+int lttng_ustconsumer_close_wakeup_fd(struct lttng_consumer_stream *stream)
+{
+       assert(stream);
+       assert(stream->ustream);
+
+       return ustctl_stream_close_wakeup_fd(stream->ustream);
+}
+
 /*
  * Populate index values of a UST stream. Values are set in big endian order.
  *
@@ -2134,6 +2111,45 @@ end:
        return ret;
 }
 
+/*
+ * Stop a given metadata channel timer if enabled and close the wait fd which
+ * is the poll pipe of the metadata stream.
+ *
+ * This MUST be called with the metadata channel acquired.
+ */
+void lttng_ustconsumer_close_metadata(struct lttng_consumer_channel *metadata)
+{
+       int ret;
+
+       assert(metadata);
+       assert(metadata->type == CONSUMER_CHANNEL_TYPE_METADATA);
+
+       DBG("Closing metadata channel key %" PRIu64, metadata->key);
+
+       if (metadata->switch_timer_enabled == 1) {
+               consumer_timer_switch_stop(metadata);
+       }
+
+       if (!metadata->metadata_stream) {
+               goto end;
+       }
+
+       /*
+        * Closing write side so the thread monitoring the stream wakes up if any
+        * and clean the metadata stream.
+        */
+       if (metadata->metadata_stream->ust_metadata_poll_pipe[1] >= 0) {
+               ret = close(metadata->metadata_stream->ust_metadata_poll_pipe[1]);
+               if (ret < 0) {
+                       PERROR("closing metadata pipe write side");
+               }
+               metadata->metadata_stream->ust_metadata_poll_pipe[1] = -1;
+       }
+
+end:
+       return;
+}
+
 /*
  * Close every metadata stream wait fd of the metadata hash table. This
  * function MUST be used very carefully so not to run into a race between the
@@ -2143,7 +2159,7 @@ end:
  * producer so calling this is safe because we are assured that no state change
  * can occur in the metadata thread for the streams in the hash table.
  */
-void lttng_ustconsumer_close_metadata(struct lttng_ht *metadata_ht)
+void lttng_ustconsumer_close_all_metadata(struct lttng_ht *metadata_ht)
 {
        struct lttng_ht_iter iter;
        struct lttng_consumer_stream *stream;
@@ -2160,13 +2176,7 @@ void lttng_ustconsumer_close_metadata(struct lttng_ht *metadata_ht)
                health_code_update();
 
                pthread_mutex_lock(&stream->chan->lock);
-               /*
-                * Whatever returned value, we must continue to try to close everything
-                * so ignore it.
-                */
-               (void) _close_metadata(stream->chan);
-               DBG("Metadata wait fd %d and poll pipe fd %d closed", stream->wait_fd,
-                               stream->ust_metadata_poll_pipe[1]);
+               lttng_ustconsumer_close_metadata(stream->chan);
                pthread_mutex_unlock(&stream->chan->lock);
 
        }
This page took 0.027354 seconds and 5 git commands to generate.