Fix: relayd live don't send incomplete stream list
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Sun, 23 Aug 2015 19:52:26 +0000 (12:52 -0700)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 24 Sep 2015 02:06:17 +0000 (22:06 -0400)
Sample the "closed" flag with session lock held.
Also, if the session connection is closed while we attach to it, reply
with HUP, because there are risks of attaching to an incomplete session
(e.g. the metadata stream could be already closed).

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
src/bin/lttng-relayd/live.c

index 283aacc3c124d32645673666c6c741e1eeeca7f5..51457400bbff43c00b738503bcd223db33325449 100644 (file)
@@ -266,7 +266,7 @@ end_unlock:
 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)
+               uint32_t *nb_created, bool *closed)
 {
        int ret;
        struct lttng_ht_iter iter;
@@ -280,6 +280,10 @@ int make_viewer_streams(struct relay_session *session,
         */
        pthread_mutex_lock(&session->lock);
 
+       if (session->connection_closed) {
+               *closed = true;
+       }
+
        /*
         * Create viewer streams for relay streams that are ready to be
         * used for a the given session id only.
@@ -861,6 +865,7 @@ int viewer_get_new_streams(struct relay_connection *conn)
        struct lttng_viewer_new_streams_response response;
        struct relay_session *session;
        uint64_t session_id;
+       bool closed = false;
 
        assert(conn);
 
@@ -896,7 +901,7 @@ int viewer_get_new_streams(struct relay_connection *conn)
        response.status = htobe32(LTTNG_VIEWER_NEW_STREAMS_OK);
 
        ret = make_viewer_streams(session, LTTNG_VIEWER_SEEK_LAST, &nb_total, &nb_unsent,
-                       &nb_created);
+                       &nb_created, &closed);
        if (ret < 0) {
                goto end_put_session;
        }
@@ -905,12 +910,11 @@ int viewer_get_new_streams(struct relay_connection *conn)
        response.streams_count = htobe32(nb_streams);
 
        /*
-        * If the session is closed and we have no new streams to send,
-        * it means that the viewer has already received the whole trace
-        * for this session and should now close it.
+        * If the session is closed, HUP when there are no more streams.
         */
-       if (nb_total == 0 && session->connection_closed) {
+       if (closed && nb_total == 0) {
                send_streams = 0;
+               response.streams_count = 0;
                response.status = htobe32(LTTNG_VIEWER_NEW_STREAMS_HUP);
                goto send_reply;
        }
@@ -963,6 +967,7 @@ int viewer_attach_session(struct relay_connection *conn)
        struct lttng_viewer_attach_session_request request;
        struct lttng_viewer_attach_session_response response;
        struct relay_session *session = NULL;
+       bool closed = false;
 
        assert(conn);
 
@@ -1021,12 +1026,26 @@ int viewer_attach_session(struct relay_connection *conn)
                goto send_reply;
        }
 
-       ret = make_viewer_streams(session, seek_type, &nb_streams, NULL, NULL);
+       ret = make_viewer_streams(session, seek_type, &nb_streams, NULL,
+                       NULL, &closed);
        if (ret < 0) {
                goto end_put_session;
        }
        response.streams_count = htobe32(nb_streams);
 
+       /*
+        * If the session is closed when the viewer is attaching, it
+        * means some of the streams may have been concurrently removed,
+        * so we don't allow the viewer to attach, even if there are
+        * streams available.
+        */
+       if (closed) {
+               send_streams = 0;
+               response.streams_count = 0;
+               response.status = htobe32(LTTNG_VIEWER_NEW_STREAMS_HUP);
+               goto send_reply;
+       }
+
 send_reply:
        health_code_update();
        ret = send_response(conn->sock, &response, sizeof(response));
This page took 0.027714 seconds and 4 git commands to generate.