/*
- * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
+ * Copyright (C) 2011 EfficiOS Inc.
* Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
* Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
*
#define _LGPL_SOURCE
#include <assert.h>
#include <lttng/ust-ctl.h>
+#include <lttng/ust-sigbus.h>
#include <poll.h>
#include <pthread.h>
#include <stdlib.h>
extern struct lttng_consumer_global_data the_consumer_data;
extern int consumer_poll_timeout;
+DEFINE_LTTNG_UST_SIGBUS_STATE();
+
/*
* Free channel object and all streams associated with it. This MUST be used
* only and only if the channel has _NEVER_ been added to the global channel
health_code_update();
- cds_list_del(&stream->send_node);
+ cds_list_del_init(&stream->send_node);
lttng_ust_ctl_destroy_stream(stream->ustream);
lttng_trace_chunk_put(stream->trace_chunk);
free(stream);
* global.
*/
stream->globally_visible = 1;
- cds_list_del(&stream->send_node);
+ cds_list_del_init(&stream->send_node);
ret = lttng_pipe_write(stream_pipe, &stream, sizeof(stream));
if (ret < 0) {
}
if (!stream->quiescent) {
- lttng_ust_ctl_flush_buffer(stream->ustream, 0);
+ ret = lttng_ust_ctl_flush_buffer(stream->ustream, 0);
+ if (ret) {
+ ERR("Failed to flush buffer while flushing channel: channel key = %" PRIu64 ", channel name = '%s'",
+ chan_key, channel->name);
+ ret = LTTNG_ERR_BUFFER_FLUSH_FAILED;
+ pthread_mutex_unlock(&stream->lock);
+ goto error;
+ }
stream->quiescent = true;
}
next:
* will make sure to clean that list.
*/
consumer_stream_destroy(metadata->metadata_stream, NULL);
- cds_list_del(&metadata->metadata_stream->send_node);
metadata->metadata_stream = NULL;
+ lttng_wait_queue_wake_all(&metadata->metadata_pushed_wait_queue);
+
send_streams_error:
error_no_stream:
end:
* Ask the sessiond if we have new metadata waiting and update the
* consumer metadata cache.
*/
- ret = lttng_ustconsumer_request_metadata(ctx, metadata_channel, 0, 1);
+ ret = lttng_ustconsumer_request_metadata(ctx, metadata_channel, false, 1);
if (ret < 0) {
goto error;
}
metadata_stream = metadata_channel->metadata_stream;
assert(metadata_stream);
- pthread_mutex_lock(&metadata_stream->lock);
+ metadata_stream->read_subbuffer_ops.lock(metadata_stream);
if (relayd_id != (uint64_t) -1ULL) {
metadata_stream->net_seq_idx = relayd_id;
ret = consumer_send_relayd_stream(metadata_stream, path);
ret = consumer_stream_create_output_files(metadata_stream,
false);
}
- pthread_mutex_unlock(&metadata_stream->lock);
if (ret < 0) {
goto error_stream;
}
do {
health_code_update();
-
ret = lttng_consumer_read_subbuffer(metadata_stream, ctx, true);
if (ret < 0) {
goto error_stream;
} while (ret > 0);
error_stream:
+ metadata_stream->read_subbuffer_ops.unlock(metadata_stream);
/*
- * Clean up the stream completly because the next snapshot will use a new
- * metadata stream.
+ * Clean up the stream completely because the next snapshot will use a
+ * new metadata stream.
*/
consumer_stream_destroy(metadata_stream, NULL);
- cds_list_del(&metadata_stream->send_node);
metadata_channel->metadata_stream = NULL;
+ lttng_wait_queue_wake_all(&metadata_channel->metadata_pushed_wait_queue);
error:
rcu_read_unlock();
if (use_relayd) {
ret = consumer_send_relayd_stream(stream, path);
if (ret < 0) {
- goto error_unlock;
+ goto error_close_stream;
}
} else {
ret = consumer_stream_create_output_files(stream,
false);
if (ret < 0) {
- goto error_unlock;
+ goto error_close_stream;
}
DBG("UST consumer snapshot stream (%" PRIu64 ")",
stream->key);
* Else, if quiescent, it has already been done by the prior stop.
*/
if (!stream->quiescent) {
- lttng_ust_ctl_flush_buffer(stream->ustream, 0);
+ ret = lttng_ust_ctl_flush_buffer(stream->ustream, 0);
+ if (ret < 0) {
+ ERR("Failed to flush buffer during snapshot of channel: channel key = %" PRIu64 ", channel name = '%s'",
+ channel->key, channel->name);
+ goto error_unlock;
+ }
}
ret = lttng_ustconsumer_take_snapshot(stream);
if (ret < 0) {
ERR("Taking UST snapshot");
- goto error_unlock;
+ goto error_close_stream;
}
ret = lttng_ustconsumer_get_produced_snapshot(stream, &produced_pos);
if (ret < 0) {
ERR("Produced UST snapshot position");
- goto error_unlock;
+ goto error_close_stream;
}
ret = lttng_ustconsumer_get_consumed_snapshot(stream, &consumed_pos);
if (ret < 0) {
ERR("Consumerd UST snapshot position");
- goto error_unlock;
+ goto error_close_stream;
}
/*
*/
int lttng_ustconsumer_recv_metadata(int sock, uint64_t key, uint64_t offset,
uint64_t len, uint64_t version,
- struct lttng_consumer_channel *channel, int timer, int wait)
+ struct lttng_consumer_channel *channel, bool invoked_by_timer, int wait)
{
int ret, ret_code = LTTCOMM_CONSUMERD_SUCCESS;
char *metadata_str;
* metadata position to ensure the metadata poll thread consumes
* the whole cache.
*/
- pthread_mutex_lock(&channel->metadata_stream->lock);
- metadata_stream_reset_cache_consumed_position(
- channel->metadata_stream);
- pthread_mutex_unlock(&channel->metadata_stream->lock);
+
+ /*
+ * channel::metadata_stream can be null when the metadata
+ * channel is under a snapshot session type. No need to update
+ * the stream position in that scenario.
+ */
+ if (channel->metadata_stream != NULL) {
+ pthread_mutex_lock(&channel->metadata_stream->lock);
+ metadata_stream_reset_cache_consumed_position(
+ channel->metadata_stream);
+ pthread_mutex_unlock(&channel->metadata_stream->lock);
+ } else {
+ /* Validate we are in snapshot mode. */
+ assert(!channel->monitor);
+ }
/* Fall-through. */
case CONSUMER_METADATA_CACHE_WRITE_STATUS_APPENDED_CONTENT:
/*
if (!wait) {
goto end_free;
}
- while (consumer_metadata_cache_flushed(channel, offset + len, timer)) {
- DBG("Waiting for metadata to be flushed");
-
- health_code_update();
- usleep(DEFAULT_METADATA_AVAILABILITY_WAIT_TIME);
- }
+ consumer_wait_metadata_cache_flushed(channel, offset + len, invoked_by_timer);
end_free:
free(metadata_str);
switch (msg.cmd_type) {
case LTTNG_CONSUMER_ADD_RELAYD_SOCKET:
{
+ uint32_t major = msg.u.relayd_sock.major;
+ uint32_t minor = msg.u.relayd_sock.minor;
+ enum lttcomm_sock_proto protocol =
+ (enum lttcomm_sock_proto) msg.u.relayd_sock
+ .relayd_socket_protocol;
+
/* Session daemon status message are handled in the following call. */
consumer_add_relayd_socket(msg.u.relayd_sock.net_index,
- msg.u.relayd_sock.type, ctx, sock, consumer_sockpoll,
- &msg.u.relayd_sock.sock, msg.u.relayd_sock.session_id,
- msg.u.relayd_sock.relayd_session_id);
+ msg.u.relayd_sock.type, ctx, sock,
+ consumer_sockpoll, msg.u.relayd_sock.session_id,
+ msg.u.relayd_sock.relayd_session_id, major,
+ minor, protocol);
goto end_nosignal;
}
case LTTNG_CONSUMER_DESTROY_RELAYD:
health_code_update();
ret = lttng_ustconsumer_recv_metadata(sock, key, offset, len,
- version, found_channel, 0, 1);
+ version, found_channel, false, 1);
if (ret < 0) {
/* error receiving from sessiond */
goto error_push_metadata_fatal;
return ret_func;
}
-void lttng_ust_flush_buffer(
- struct lttng_consumer_stream *stream, int producer_active)
+int lttng_ust_flush_buffer(struct lttng_consumer_stream *stream,
+ int producer_active)
{
assert(stream);
assert(stream->ustream);
- lttng_ust_ctl_flush_buffer(stream->ustream, producer_active);
+ return lttng_ust_ctl_flush_buffer(stream->ustream, producer_active);
}
/*
return lttng_ust_ctl_snapshot_get_consumed(stream->ustream, pos);
}
-void lttng_ustconsumer_flush_buffer(struct lttng_consumer_stream *stream,
+int lttng_ustconsumer_flush_buffer(struct lttng_consumer_stream *stream,
int producer)
{
assert(stream);
assert(stream->ustream);
- lttng_ust_ctl_flush_buffer(stream->ustream, producer);
+ return lttng_ust_ctl_flush_buffer(stream->ustream, producer);
}
-void lttng_ustconsumer_clear_buffer(struct lttng_consumer_stream *stream)
+int lttng_ustconsumer_clear_buffer(struct lttng_consumer_stream *stream)
{
assert(stream);
assert(stream->ustream);
- lttng_ust_ctl_clear_buffer(stream->ustream);
+ return lttng_ust_ctl_clear_buffer(stream->ustream);
}
int lttng_ustconsumer_get_current_timestamp(
pthread_mutex_lock(&stream->lock);
if (!stream->quiescent) {
- lttng_ust_ctl_flush_buffer(stream->ustream, 0);
- stream->quiescent = true;
+ if (lttng_ust_ctl_flush_buffer(stream->ustream, 0) < 0) {
+ ERR("Failed to flush buffer on stream hang-up");
+ } else {
+ stream->quiescent = true;
+ }
}
- pthread_mutex_unlock(&stream->lock);
+
stream->hangup_flush_done = 1;
+ pthread_mutex_unlock(&stream->lock);
}
void lttng_ustconsumer_del_channel(struct lttng_consumer_channel *chan)
goto end;
}
stream->ust_metadata_pushed += write_len;
+ lttng_wait_queue_wake_all(&stream->chan->metadata_pushed_wait_queue);
assert(stream->chan->metadata_cache->contents.size >=
stream->ust_metadata_pushed);
* a metadata packet. Since the subbuffer is fully filled (with padding,
* if needed), the stream is "quiescent" after this commit.
*/
- lttng_ust_ctl_flush_buffer(stream->ustream, 1);
- stream->quiescent = true;
+ if (lttng_ust_ctl_flush_buffer(stream->ustream, 1)) {
+ ERR("Failed to flush buffer while commiting one metadata packet");
+ ret = -EIO;
+ } else {
+ stream->quiescent = true;
+ }
end:
pthread_mutex_unlock(&stream->chan->metadata_cache->lock);
return ret;
* Request metadata from the sessiond, but don't wait for the flush
* because we locked the metadata thread.
*/
- ret = lttng_ustconsumer_request_metadata(ctx, metadata_channel, 0, 0);
+ ret = lttng_ustconsumer_request_metadata(ctx, metadata_channel, false, 0);
pthread_mutex_lock(&metadata_stream->lock);
if (ret < 0) {
status = SYNC_METADATA_STATUS_ERROR;
* pushed out due to concurrent interaction with the session daemon.
*/
int lttng_ustconsumer_request_metadata(struct lttng_consumer_local_data *ctx,
- struct lttng_consumer_channel *channel, int timer, int wait)
+ struct lttng_consumer_channel *channel, bool invoked_by_timer, int wait)
{
struct lttcomm_metadata_request_msg request;
struct lttcomm_consumer_msg msg;
health_code_update();
ret = lttng_ustconsumer_recv_metadata(ctx->consumer_metadata_socket,
- key, offset, len, version, channel, timer, wait);
+ key, offset, len, version, channel, invoked_by_timer, wait);
if (ret >= 0) {
/*
* Only send the status msg if the sessiond is alive meaning a positive
return lttng_ust_ctl_get_stream_id(stream->ustream, stream_id);
}
+
+void lttng_ustconsumer_sigbus_handle(void *addr)
+{
+ lttng_ust_ctl_sigbus_handle(addr);
+}