From: Jérémie Galarneau Date: Thu, 19 Sep 2019 17:48:20 +0000 (-0400) Subject: Fix: relayd: session destruction does not complete in live mode X-Git-Tag: v2.11.0-rc4~19 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=279cc4fe6584ba00b560e2fe59cce2eff4604820;p=lttng-tools.git Fix: relayd: session destruction does not complete in live mode Live clients currently hold a reference to their relay_session's trace chunk through the viewer streams. This causes the destruction of live session to hang for as long as a client is consuming a session's contents. The reason for the hang itself is that the "quiet" rotation performed as part of the session's destruction can never complete. Indeed, a rotation completes when the last reference to the trace chunk being archived is released. Since viewer streams hold references to this trace chunk, they bound its lifetime to their own lifetime, resulting in the destruction operation appearing to hang to users of liblttng-ctl / the lttng client. Since session rotations are not allowed for live sessions, it is safe to presume that a session's output folder hierarchy will not change over its lifetime with the exception of sub-folder additions, such as in per-PID tracing mode where new traces may be added at any time within the session's output directory. The viewer session now copies its corresponding relay_session's trace chunk to obtain a 'user' mode trace chunk. A user mode trace chunk will prevent the viewer session from modifying the session output hierarchy and prevent it from keeping the relay_session's trace chunk "alive". The viewer stream simply use this trace chunk to perform their filesystem operations, but they no longer extend the lifetime of the relayd_session trace chunks. Signed-off-by: Jérémie Galarneau --- diff --git a/src/bin/lttng-relayd/live.c b/src/bin/lttng-relayd/live.c index dc8238c94..88bb7363d 100644 --- a/src/bin/lttng-relayd/live.c +++ b/src/bin/lttng-relayd/live.c @@ -276,10 +276,13 @@ end_unlock: * * Return 0 on success or else a negative value. */ -static -int make_viewer_streams(struct relay_session *session, - enum lttng_viewer_seek seek_t, uint32_t *nb_total, uint32_t *nb_unsent, - uint32_t *nb_created, bool *closed) +static int make_viewer_streams(struct relay_session *session, + struct lttng_trace_chunk *viewer_trace_chunk, + enum lttng_viewer_seek seek_t, + uint32_t *nb_total, + uint32_t *nb_unsent, + uint32_t *nb_created, + bool *closed) { int ret; struct lttng_ht_iter iter; @@ -321,7 +324,8 @@ int make_viewer_streams(struct relay_session *session, } vstream = viewer_stream_get_by_id(stream->stream_handle); if (!vstream) { - vstream = viewer_stream_create(stream, seek_t); + vstream = viewer_stream_create(stream, + viewer_trace_chunk, seek_t); if (!vstream) { ret = -1; ctf_trace_put(ctf_trace); @@ -906,7 +910,7 @@ int viewer_get_new_streams(struct relay_connection *conn) uint32_t nb_created = 0, nb_unsent = 0, nb_streams = 0, nb_total = 0; struct lttng_viewer_new_streams_request request; struct lttng_viewer_new_streams_response response; - struct relay_session *session; + struct relay_session *session = NULL; uint64_t session_id; bool closed = false; @@ -944,12 +948,23 @@ int viewer_get_new_streams(struct relay_connection *conn) response.status = htobe32(LTTNG_VIEWER_NEW_STREAMS_OK); pthread_mutex_lock(&session->lock); - ret = make_viewer_streams(session, LTTNG_VIEWER_SEEK_LAST, &nb_total, &nb_unsent, + if (!conn->viewer_session->current_trace_chunk && + session->current_trace_chunk) { + ret = viewer_session_set_trace_chunk(conn->viewer_session, + session->current_trace_chunk); + if (ret) { + goto error_unlock_session; + } + } + ret = make_viewer_streams(session, + conn->viewer_session->current_trace_chunk, + LTTNG_VIEWER_SEEK_LAST, &nb_total, &nb_unsent, &nb_created, &closed); - pthread_mutex_unlock(&session->lock); if (ret < 0) { - goto end_put_session; + goto error_unlock_session; } + pthread_mutex_unlock(&session->lock); + /* Only send back the newly created streams with the unsent ones. */ nb_streams = nb_created + nb_unsent; response.streams_count = htobe32(nb_streams); @@ -998,6 +1013,10 @@ end_put_session: } error: return ret; +error_unlock_session: + pthread_mutex_unlock(&session->lock); + session_put(session); + return ret; } /* @@ -1073,12 +1092,20 @@ int viewer_attach_session(struct relay_connection *conn) goto send_reply; } - ret = make_viewer_streams(session, seek_type, &nb_streams, NULL, - NULL, &closed); + if (!conn->viewer_session->current_trace_chunk && + session->current_trace_chunk) { + ret = viewer_session_set_trace_chunk(conn->viewer_session, + session->current_trace_chunk); + if (ret) { + goto end_put_session; + } + } + ret = make_viewer_streams(session, + conn->viewer_session->current_trace_chunk, seek_type, + &nb_streams, NULL, NULL, &closed); if (ret < 0) { goto end_put_session; } - pthread_mutex_unlock(&session->lock); session_put(session); session = NULL; @@ -1158,7 +1185,7 @@ static int try_open_index(struct relay_viewer_stream *vstream, goto end; } vstream->index_file = lttng_index_file_create_from_trace_chunk_read_only( - rstream->trace_chunk, rstream->path_name, + vstream->stream_file.trace_chunk, rstream->path_name, rstream->channel_name, rstream->tracefile_size, vstream->current_tracefile_id, lttng_to_index_major(connection_major, connection_minor), diff --git a/src/bin/lttng-relayd/viewer-session.c b/src/bin/lttng-relayd/viewer-session.c index 5f9c7c576..7ff58ed96 100644 --- a/src/bin/lttng-relayd/viewer-session.c +++ b/src/bin/lttng-relayd/viewer-session.c @@ -101,6 +101,7 @@ static int viewer_session_detach(struct relay_viewer_session *vsession, void viewer_session_destroy(struct relay_viewer_session *vsession) { + lttng_trace_chunk_put(vsession->current_trace_chunk); free(vsession); } @@ -183,3 +184,25 @@ end: pthread_mutex_unlock(&session->lock); return found; } + +int viewer_session_set_trace_chunk(struct relay_viewer_session *vsession, + struct lttng_trace_chunk *relay_session_trace_chunk) +{ + int ret = 0; + struct lttng_trace_chunk *viewer_chunk; + + assert(relay_session_trace_chunk); + assert(!vsession->current_trace_chunk); + + DBG("Copying relay session's current trace chunk to the viewer session"); + viewer_chunk = lttng_trace_chunk_copy(relay_session_trace_chunk); + if (!viewer_chunk) { + ERR("Failed to create a viewer trace chunk from the relay session's current chunk"); + ret = -1; + goto end; + } + + vsession->current_trace_chunk = viewer_chunk; +end: + return ret; +} diff --git a/src/bin/lttng-relayd/viewer-session.h b/src/bin/lttng-relayd/viewer-session.h index 249a483d5..c127f69c1 100644 --- a/src/bin/lttng-relayd/viewer-session.h +++ b/src/bin/lttng-relayd/viewer-session.h @@ -27,6 +27,7 @@ #include #include +#include #include "session.h" @@ -39,6 +40,8 @@ struct relay_viewer_session { */ struct cds_list_head session_list; /* RCU list. */ pthread_mutex_t session_list_lock; /* Protects list updates. */ + /* Once set, the current trace chunk of a viewer must not change. */ + struct lttng_trace_chunk *current_trace_chunk; }; struct relay_viewer_session *viewer_session_create(void); @@ -51,5 +54,7 @@ int viewer_session_is_attached(struct relay_viewer_session *vsession, struct relay_session *session); void viewer_session_close_one_session(struct relay_viewer_session *vsession, struct relay_session *session); +int viewer_session_set_trace_chunk(struct relay_viewer_session *vsession, + struct lttng_trace_chunk *relay_session_trace_chunk); #endif /* _VIEWER_SESSION_H */ diff --git a/src/bin/lttng-relayd/viewer-stream.c b/src/bin/lttng-relayd/viewer-stream.c index 70cd1cea1..25ee35e5c 100644 --- a/src/bin/lttng-relayd/viewer-stream.c +++ b/src/bin/lttng-relayd/viewer-stream.c @@ -42,11 +42,12 @@ static void viewer_stream_destroy_rcu(struct rcu_head *head) } struct relay_viewer_stream *viewer_stream_create(struct relay_stream *stream, + struct lttng_trace_chunk *viewer_trace_chunk, enum lttng_viewer_seek seek_t) { struct relay_viewer_stream *vstream = NULL; const bool acquired_reference = lttng_trace_chunk_get( - stream->trace_chunk); + viewer_trace_chunk); if (!acquired_reference) { goto error; @@ -58,7 +59,8 @@ struct relay_viewer_stream *viewer_stream_create(struct relay_stream *stream, goto error; } - vstream->stream_file.trace_chunk = stream->trace_chunk; + vstream->stream_file.trace_chunk = viewer_trace_chunk; + viewer_trace_chunk = NULL; vstream->path_name = lttng_strndup(stream->path_name, LTTNG_VIEWER_PATH_MAX); if (vstream->path_name == NULL) { PERROR("relay viewer path_name alloc"); @@ -130,7 +132,8 @@ struct relay_viewer_stream *viewer_stream_create(struct relay_stream *stream, const uint32_t connection_minor = stream->trace->session->minor; vstream->index_file = lttng_index_file_create_from_trace_chunk_read_only( - stream->trace_chunk, stream->path_name, + vstream->stream_file.trace_chunk, + stream->path_name, stream->channel_name, stream->tracefile_size, vstream->current_tracefile_id, lttng_to_index_major(connection_major, @@ -170,6 +173,9 @@ error: if (vstream) { viewer_stream_destroy(vstream); } + if (viewer_trace_chunk) { + lttng_trace_chunk_put(viewer_trace_chunk); + } return NULL; } @@ -313,7 +319,8 @@ int viewer_stream_rotate(struct relay_viewer_stream *vstream) } vstream->index_file = lttng_index_file_create_from_trace_chunk_read_only( - stream->trace_chunk, stream->path_name, + vstream->stream_file.trace_chunk, + stream->path_name, stream->channel_name, stream->tracefile_size, vstream->current_tracefile_id, diff --git a/src/bin/lttng-relayd/viewer-stream.h b/src/bin/lttng-relayd/viewer-stream.h index 7c42dfad3..18a3521d7 100644 --- a/src/bin/lttng-relayd/viewer-stream.h +++ b/src/bin/lttng-relayd/viewer-stream.h @@ -81,6 +81,7 @@ struct relay_viewer_stream { }; struct relay_viewer_stream *viewer_stream_create(struct relay_stream *stream, + struct lttng_trace_chunk *viewer_trace_chunk, enum lttng_viewer_seek seek_t); struct relay_viewer_stream *viewer_stream_get_by_id(uint64_t id);