Fix: relayd: live: crash when creating viewer streams
[lttng-tools.git] / src / bin / lttng-relayd / live.c
index 74c28a45784a1962aa9c068a63cccf9461f5a600..9a3d78ef0fc3a0632476d131202b325d77e17e82 100644 (file)
@@ -831,9 +831,18 @@ int viewer_list_sessions(struct relay_connection *conn)
 
                health_code_update();
 
+               pthread_mutex_lock(&session->lock);
                if (session->connection_closed) {
                        /* Skip closed session */
-                       continue;
+                       goto next_session;
+               }
+               if (!session->current_trace_chunk) {
+                       /*
+                        * Skip un-attachable session. It is either
+                        * being destroyed or has not had a trace
+                        * chunk created against it yet.
+                        */
+                       goto next_session;
                }
 
                if (count >= buf_count) {
@@ -844,7 +853,7 @@ int viewer_list_sessions(struct relay_connection *conn)
                                new_buf_count * sizeof(*send_session_buf));
                        if (!newbuf) {
                                ret = -1;
-                               break;
+                               goto break_loop;
                        }
                        send_session_buf = newbuf;
                        buf_count = new_buf_count;
@@ -854,12 +863,12 @@ int viewer_list_sessions(struct relay_connection *conn)
                                session->session_name,
                                sizeof(send_session->session_name))) {
                        ret = -1;
-                       break;
+                       goto break_loop;
                }
                if (lttng_strncpy(send_session->hostname, session->hostname,
                                sizeof(send_session->hostname))) {
                        ret = -1;
-                       break;
+                       goto break_loop;
                }
                send_session->id = htobe64(session->id);
                send_session->live_timer = htobe32(session->live_timer);
@@ -870,6 +879,12 @@ int viewer_list_sessions(struct relay_connection *conn)
                }
                send_session->streams = htobe32(session->stream_count);
                count++;
+       next_session:
+               pthread_mutex_unlock(&session->lock);
+               continue;
+       break_loop:
+               pthread_mutex_unlock(&session->lock);
+               break;
        }
        rcu_read_unlock();
        if (ret < 0) {
@@ -939,15 +954,22 @@ int viewer_get_new_streams(struct relay_connection *conn)
        }
 
        if (!viewer_session_is_attached(conn->viewer_session, session)) {
-               send_streams = 0;
                response.status = htobe32(LTTNG_VIEWER_NEW_STREAMS_ERR);
                goto send_reply;
        }
 
-       send_streams = 1;
-       response.status = htobe32(LTTNG_VIEWER_NEW_STREAMS_OK);
-
        pthread_mutex_lock(&session->lock);
+       if (!session->current_trace_chunk) {
+               /*
+                * Means the session is being destroyed. React the same way
+                * as if it could not be found at all.
+                */
+               DBG("Relay session %" PRIu64 " has no current trace chunk, replying LTTNG_VIEWER_NEW_STREAMS_ERR",
+                               session_id);
+               response.status = htobe32(LTTNG_VIEWER_NEW_STREAMS_ERR);
+               goto send_reply_unlock;
+       }
+
        if (!conn->viewer_session->current_trace_chunk &&
                        session->current_trace_chunk) {
                ret = viewer_session_set_trace_chunk(conn->viewer_session,
@@ -963,7 +985,8 @@ int viewer_get_new_streams(struct relay_connection *conn)
        if (ret < 0) {
                goto error_unlock_session;
        }
-       pthread_mutex_unlock(&session->lock);
+       send_streams = 1;
+       response.status = htobe32(LTTNG_VIEWER_NEW_STREAMS_OK);
 
        /* Only send back the newly created streams with the unsent ones. */
        nb_streams = nb_created + nb_unsent;
@@ -977,8 +1000,10 @@ int viewer_get_new_streams(struct relay_connection *conn)
                send_streams = 0;
                response.streams_count = 0;
                response.status = htobe32(LTTNG_VIEWER_NEW_STREAMS_HUP);
-               goto send_reply;
+               goto send_reply_unlock;
        }
+send_reply_unlock:
+       pthread_mutex_unlock(&session->lock);
 
 send_reply:
        health_code_update();
@@ -1065,6 +1090,15 @@ int viewer_attach_session(struct relay_connection *conn)
        DBG("Attach session ID %" PRIu64 " received", session_id);
 
        pthread_mutex_lock(&session->lock);
+       if (!session->current_trace_chunk) {
+               /*
+                * Session is either being destroyed or it never had a trace
+                * chunk created against it.
+                */
+               DBG("Session requested by live client has no current trace chunk, returning unknown session");
+               response.status = htobe32(LTTNG_VIEWER_ATTACH_UNK);
+               goto send_reply;
+       }
        if (session->live_timer == 0) {
                DBG("Not live session");
                response.status = htobe32(LTTNG_VIEWER_ATTACH_NOT_LIVE);
This page took 0.025607 seconds and 4 git commands to generate.