Fix: relayd: live: mishandled initial null trace chunk
[lttng-tools.git] / src / bin / lttng-relayd / live.c
index 5877467c0d5598f0cbdc7481f08c144a0b7580b1..962fe0fd14a340c9e903f6410d09b1b6f386a3de 100644 (file)
@@ -281,7 +281,7 @@ static int make_viewer_streams(struct relay_session *relay_session,
        struct ctf_trace *ctf_trace;
        struct relay_stream *relay_stream = NULL;
 
-       assert(relay_session);
+       LTTNG_ASSERT(relay_session);
        ASSERT_LOCKED(relay_session->lock);
 
        if (relay_session->connection_closed) {
@@ -384,8 +384,6 @@ static int make_viewer_streams(struct relay_session *relay_session,
                                                goto error_unlock;
                                        }
                                } else {
-                                       bool reference_acquired;
-
                                        /*
                                         * Transition the viewer session into the newest trace chunk available.
                                         */
@@ -402,11 +400,26 @@ static int make_viewer_streams(struct relay_session *relay_session,
                                                }
                                        }
 
-                                       reference_acquired = lttng_trace_chunk_get(
-                                                       viewer_session->current_trace_chunk);
-                                       assert(reference_acquired);
-                                       viewer_stream_trace_chunk =
-                                                       viewer_session->current_trace_chunk;
+                                       if (relay_stream->trace_chunk) {
+                                               /*
+                                                * If the corresponding relay
+                                                * stream's trace chunk is set,
+                                                * the viewer stream will be
+                                                * created under it.
+                                                *
+                                                * Note that a relay stream can
+                                                * have a NULL output trace
+                                                * chunk (for instance, after a
+                                                * clear against a stopped
+                                                * session).
+                                                */
+                                               const bool reference_acquired = lttng_trace_chunk_get(
+                                                               viewer_session->current_trace_chunk);
+
+                                               LTTNG_ASSERT(reference_acquired);
+                                               viewer_stream_trace_chunk =
+                                                               viewer_session->current_trace_chunk;
+                                       }
                                }
 
                                viewer_stream = viewer_stream_create(
@@ -1113,7 +1126,7 @@ int viewer_get_new_streams(struct relay_connection *conn)
        uint64_t session_id;
        bool closed = false;
 
-       assert(conn);
+       LTTNG_ASSERT(conn);
 
        DBG("Get new streams received");
 
@@ -1142,10 +1155,19 @@ int viewer_get_new_streams(struct relay_connection *conn)
                goto send_reply;
        }
 
+       /*
+        * For any new stream, create it with LTTNG_VIEWER_SEEK_BEGINNING since
+        * that at this point the client is already attached to the session.Aany
+        * initial stream will have been created with the seek type at attach
+        * time (for now most readers use the LTTNG_VIEWER_SEEK_LAST on attach).
+        * Otherwise any event happening in a new stream between the attach and
+        * a call to viewer_get_new_streams will be "lost" (never received) from
+        * the viewer's point of view.
+        */
        pthread_mutex_lock(&session->lock);
        ret = make_viewer_streams(session,
                        conn->viewer_session,
-                       LTTNG_VIEWER_SEEK_LAST, &nb_total, &nb_unsent,
+                       LTTNG_VIEWER_SEEK_BEGINNING, &nb_total, &nb_unsent,
                        &nb_created, &closed);
        if (ret < 0) {
                goto error_unlock_session;
@@ -1226,7 +1248,7 @@ int viewer_attach_session(struct relay_connection *conn)
        bool closed = false;
        uint64_t session_id;
 
-       assert(conn);
+       LTTNG_ASSERT(conn);
 
        health_code_update();
 
@@ -1509,7 +1531,7 @@ static int check_index_status(struct relay_viewer_stream *vstream,
                                vstream->stream->stream_handle);
                        goto index_ready;
                }
-               assert(tracefile_array_seq_in_file(rstream->tfa,
+               LTTNG_ASSERT(tracefile_array_seq_in_file(rstream->tfa,
                                vstream->current_tracefile_id,
                                vstream->index_sent_seqcount));
        }
@@ -1533,7 +1555,7 @@ void viewer_stream_rotate_to_trace_chunk(struct relay_viewer_stream *vstream,
                const bool acquired_reference = lttng_trace_chunk_get(
                                new_trace_chunk);
 
-               assert(acquired_reference);
+               LTTNG_ASSERT(acquired_reference);
        }
 
        vstream->stream_file.trace_chunk = new_trace_chunk;
@@ -1558,7 +1580,7 @@ int viewer_get_next_index(struct relay_connection *conn)
        struct ctf_trace *ctf_trace = NULL;
        struct relay_viewer_stream *metadata_viewer_stream = NULL;
 
-       assert(conn);
+       LTTNG_ASSERT(conn);
 
        DBG("Viewer get next index");
 
@@ -1660,7 +1682,7 @@ int viewer_get_next_index(struct relay_connection *conn)
                goto send_reply;
        }
        /* At this point, ret is 0 thus we will be able to read the index. */
-       assert(!ret);
+       LTTNG_ASSERT(!ret);
 
        /* Try to open an index if one is needed for that stream. */
        ret = try_open_index(vstream, rstream);
@@ -1932,7 +1954,7 @@ int viewer_get_metadata(struct relay_connection *conn)
        struct lttng_viewer_metadata_packet reply;
        struct relay_viewer_stream *vstream = NULL;
 
-       assert(conn);
+       LTTNG_ASSERT(conn);
 
        DBG("Relay get metadata");
 
@@ -2007,8 +2029,9 @@ int viewer_get_metadata(struct relay_connection *conn)
                }
        }
 
-       if (conn->viewer_session->current_trace_chunk !=
-                       vstream->stream_file.trace_chunk) {
+       if (conn->viewer_session->current_trace_chunk &&
+                       conn->viewer_session->current_trace_chunk !=
+                                       vstream->stream_file.trace_chunk) {
                bool acquired_reference;
 
                DBG("Viewer session and viewer stream chunk differ: "
@@ -2017,7 +2040,7 @@ int viewer_get_metadata(struct relay_connection *conn)
                                vstream->stream_file.trace_chunk);
                lttng_trace_chunk_put(vstream->stream_file.trace_chunk);
                acquired_reference = lttng_trace_chunk_get(conn->viewer_session->current_trace_chunk);
-               assert(acquired_reference);
+               LTTNG_ASSERT(acquired_reference);
                vstream->stream_file.trace_chunk =
                        conn->viewer_session->current_trace_chunk;
                viewer_stream_close_files(vstream);
@@ -2025,11 +2048,16 @@ int viewer_get_metadata(struct relay_connection *conn)
 
        len = vstream->stream->metadata_received - vstream->metadata_sent;
 
-       /*
-        * Either this is the first time the metadata file is read, or a
-        * rotation of the corresponding relay stream has occured.
-        */
-       if (!vstream->stream_file.handle && len > 0) {
+       if (!vstream->stream_file.trace_chunk) {
+               reply.status = htobe32(LTTNG_VIEWER_NO_NEW_METADATA);
+               len = 0;
+               goto send_reply;
+       } else if (vstream->stream_file.trace_chunk &&
+                       !vstream->stream_file.handle && len > 0) {
+               /*
+                * Either this is the first time the metadata file is read, or a
+                * rotation of the corresponding relay stream has occurred.
+                */
                struct fs_handle *fs_handle;
                char file_path[LTTNG_PATH_MAX];
                enum lttng_trace_chunk_status status;
@@ -2229,7 +2257,7 @@ int viewer_detach_session(struct relay_connection *conn)
 
        DBG("Viewer detach session received");
 
-       assert(conn);
+       LTTNG_ASSERT(conn);
 
        health_code_update();
 
This page took 0.027031 seconds and 4 git commands to generate.