Fix: lttng-live: send HUP reply when per-PID streams are gone
[lttng-tools.git] / src / bin / lttng-relayd / live.c
index 5d3449d4f451f49aaf64a6f3506a4b93c1affc3c..61acafec2098ecd70a5b1889309992e858a0e3cb 100644 (file)
@@ -17,7 +17,6 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#define _GNU_SOURCE
 #define _LGPL_SOURCE
 #include <getopt.h>
 #include <grp.h>
@@ -40,7 +39,6 @@
 #include <urcu/rculist.h>
 #include <unistd.h>
 #include <fcntl.h>
-#include <config.h>
 
 #include <lttng/lttng.h>
 #include <common/common.h>
@@ -232,10 +230,21 @@ ssize_t send_viewer_streams(struct lttcomm_sock *sock,
                send_stream.ctf_trace_id = htobe64(ctf_trace->id);
                send_stream.metadata_flag = htobe32(
                                vstream->stream->is_metadata);
-               strncpy(send_stream.path_name, vstream->path_name,
-                               sizeof(send_stream.path_name));
-               strncpy(send_stream.channel_name, vstream->channel_name,
-                               sizeof(send_stream.channel_name));
+               if (lttng_strncpy(send_stream.path_name, vstream->path_name,
+                               sizeof(send_stream.path_name))) {
+                       pthread_mutex_unlock(&vstream->stream->lock);
+                       viewer_stream_put(vstream);
+                       ret = -1;       /* Error. */
+                       goto end_unlock;
+               }
+               if (lttng_strncpy(send_stream.channel_name,
+                               vstream->channel_name,
+                               sizeof(send_stream.channel_name))) {
+                       pthread_mutex_unlock(&vstream->stream->lock);
+                       viewer_stream_put(vstream);
+                       ret = -1;       /* Error. */
+                       goto end_unlock;
+               }
 
                DBG("Sending stream %" PRIu64 " to viewer",
                                vstream->stream->stream_handle);
@@ -307,8 +316,7 @@ int make_viewer_streams(struct relay_session *session,
                                continue;
                        }
                        /*
-                        * stream published is protected by the session
-                        * lock.
+                        * stream published is protected by the session lock.
                         */
                        if (!stream->published) {
                                goto next;
@@ -327,17 +335,37 @@ int make_viewer_streams(struct relay_session *session,
                                        /* Update number of created stream counter. */
                                        (*nb_created)++;
                                }
+                               /*
+                                * Ensure a self-reference is preserved even
+                                * after we have put our local reference.
+                                */
+                               if (!viewer_stream_get(vstream)) {
+                                       ERR("Unable to get self-reference on viewer stream, logic error.");
+                                       abort();
+                               }
                        } else {
                                if (!vstream->sent_flag && nb_unsent) {
                                        /* Update number of unsent stream counter. */
                                        (*nb_unsent)++;
                                }
-                               viewer_stream_put(vstream);
                        }
                        /* Update number of total stream counter. */
                        if (nb_total) {
-                               (*nb_total)++;
+                               if (stream->is_metadata) {
+                                       if (!stream->closed ||
+                                                       stream->metadata_received > vstream->metadata_sent) {
+                                               (*nb_total)++;
+                                       }
+                               } else {
+                                       if (!stream->closed ||
+                                               !(((int64_t) (stream->prev_seq - stream->last_net_seq_num)) >= 0)) {
+
+                                               (*nb_total)++;
+                                       }
+                               }
                        }
+                       /* Put local reference. */
+                       viewer_stream_put(vstream);
                next:
                        stream_put(stream);
                }
@@ -526,10 +554,7 @@ restart:
                                goto exit;
                        }
 
-                       if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
-                               ERR("socket poll error");
-                               goto error;
-                       } else if (revents & LPOLLIN) {
+                       if (revents & LPOLLIN) {
                                /*
                                 * A new connection is requested, therefore a
                                 * viewer connection is allocated in this
@@ -572,6 +597,12 @@ restart:
                                 * exchange in cds_wfcq_enqueue.
                                 */
                                futex_nto1_wake(&viewer_conn_queue.futex);
+                       } else if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
+                               ERR("socket poll error");
+                               goto error;
+                       } else {
+                               ERR("Unexpected poll events %u for sock %d", revents, pollfd);
+                               goto error;
                        }
                }
        }
@@ -777,7 +808,7 @@ end:
 static
 int viewer_list_sessions(struct relay_connection *conn)
 {
-       int ret;
+       int ret = 0;
        struct lttng_viewer_list_sessions session_list;
        struct lttng_ht_iter iter;
        struct relay_session *session;
@@ -807,17 +838,23 @@ int viewer_list_sessions(struct relay_connection *conn)
                                new_buf_count * sizeof(*send_session_buf));
                        if (!newbuf) {
                                ret = -1;
-                               rcu_read_unlock();
-                               goto end_free;
+                               break;
                        }
                        send_session_buf = newbuf;
                        buf_count = new_buf_count;
                }
                send_session = &send_session_buf[count];
-               strncpy(send_session->session_name, session->session_name,
-                               sizeof(send_session->session_name));
-               strncpy(send_session->hostname, session->hostname,
-                               sizeof(send_session->hostname));
+               if (lttng_strncpy(send_session->session_name,
+                               session->session_name,
+                               sizeof(send_session->session_name))) {
+                       ret = -1;
+                       break;
+               }
+               if (lttng_strncpy(send_session->hostname, session->hostname,
+                               sizeof(send_session->hostname))) {
+                       ret = -1;
+                       break;
+               }
                send_session->id = htobe64(session->id);
                send_session->live_timer = htobe32(session->live_timer);
                if (session->viewer_attached) {
@@ -829,6 +866,9 @@ int viewer_list_sessions(struct relay_connection *conn)
                count++;
        }
        rcu_read_unlock();
+       if (ret < 0) {
+               goto end_free;
+       }
 
        session_list.sessions_count = htobe32(count);
 
@@ -911,7 +951,8 @@ int viewer_get_new_streams(struct relay_connection *conn)
        response.streams_count = htobe32(nb_streams);
 
        /*
-        * If the session is closed, HUP when there are no more streams.
+        * If the session is closed, HUP when there are no more streams
+        * with data.
         */
        if (closed && nb_total == 0) {
                send_streams = 0;
@@ -1081,8 +1122,8 @@ error:
 /*
  * Open the index file if needed for the given vstream.
  *
- * If an index file is successfully opened, the vstream index_fd set with
- * it.
+ * If an index file is successfully opened, the vstream will set it as its
+ * current index file.
  *
  * Return 0 on success, a negative value on error (-ENOENT if not ready yet).
  *
@@ -1093,31 +1134,23 @@ static int try_open_index(struct relay_viewer_stream *vstream,
 {
        int ret = 0;
 
-       if (vstream->index_fd) {
+       if (vstream->index_file) {
                goto end;
        }
 
        /*
         * First time, we open the index file and at least one index is ready.
         */
-       if (rstream->total_index_received == 0) {
+       if (rstream->index_received_seqcount == 0) {
                ret = -ENOENT;
                goto end;
        }
-       ret = index_open(vstream->path_name, vstream->channel_name,
+       vstream->index_file = lttng_index_file_open(vstream->path_name,
+                       vstream->channel_name,
                        vstream->stream->tracefile_count,
                        vstream->current_tracefile_id);
-       if (ret >= 0) {
-               vstream->index_fd = stream_fd_create(ret);
-               if (!vstream->index_fd) {
-                       if (close(ret)) {
-                               PERROR("close");
-                       }
-                       ret = -1;
-               } else {
-                       ret = 0;
-               }
-               goto end;
+       if (!vstream->index_file) {
+               ret = -1;
        }
 
 end:
@@ -1141,15 +1174,18 @@ static int check_index_status(struct relay_viewer_stream *vstream,
 {
        int ret;
 
-       if (trace->session->connection_closed
-                       && rstream->total_index_received
-                               == vstream->last_sent_index) {
-               /* Last index sent and session connection is closed. */
+       if ((trace->session->connection_closed || rstream->closed)
+                       && rstream->index_received_seqcount
+                               == vstream->index_sent_seqcount) {
+               /*
+                * Last index sent and session connection or relay
+                * stream are closed.
+                */
                index->status = htobe32(LTTNG_VIEWER_INDEX_HUP);
                goto hup;
        } else if (rstream->beacon_ts_end != -1ULL &&
-                       rstream->total_index_received
-                               == vstream->last_sent_index) {
+                       rstream->index_received_seqcount
+                               == vstream->index_sent_seqcount) {
                /*
                 * We've received a synchronization beacon and the last index
                 * available has been sent, the index for now is inactive.
@@ -1163,21 +1199,24 @@ static int check_index_status(struct relay_viewer_stream *vstream,
                index->timestamp_end = htobe64(rstream->beacon_ts_end);
                index->stream_id = htobe64(rstream->ctf_stream_id);
                goto index_ready;
-       } else if (rstream->total_index_received <= vstream->last_sent_index) {
+       } else if (rstream->index_received_seqcount
+                       == vstream->index_sent_seqcount) {
                /*
-                * This actually checks the case where recv == last_sent.
-                * In this case, we have not received a beacon. Therefore, we
-                * can only ask the client to retry later.
+                * This checks whether received == sent seqcount. In
+                * this case, we have not received a beacon. Therefore,
+                * we can only ask the client to retry later.
                 */
                index->status = htobe32(LTTNG_VIEWER_INDEX_RETRY);
                goto index_ready;
-       } else if (!viewer_stream_is_tracefile_seq_readable(vstream,
-                       vstream->current_tracefile_seq)) {
+       } else if (!tracefile_array_seq_in_file(rstream->tfa,
+                       vstream->current_tracefile_id,
+                       vstream->index_sent_seqcount)) {
                /*
-                * The producer has overwritten our current file. We
-                * need to rotate.
+                * The next index we want to send cannot be read either
+                * because we need to perform a rotation, or due to
+                * the producer having overwritten its trace file.
                 */
-               DBG("Viewer stream %" PRIu64 " rotation due to overwrite",
+               DBG("Viewer stream %" PRIu64 " rotation",
                                vstream->stream->stream_handle);
                ret = viewer_stream_rotate(vstream);
                if (ret < 0) {
@@ -1187,50 +1226,34 @@ static int check_index_status(struct relay_viewer_stream *vstream,
                        index->status = htobe32(LTTNG_VIEWER_INDEX_HUP);
                        goto hup;
                }
-               assert(viewer_stream_is_tracefile_seq_readable(vstream,
-                       vstream->current_tracefile_seq));
-               /* ret == 0 means successful so we continue. */
-               ret = 0;
-       } else {
-               ssize_t read_ret;
-               char tmp[1];
-
                /*
-                * Use EOF on current index file to find out when we
-                * need to rotate.
+                * If we have been pushed due to overwrite, it
+                * necessarily means there is data that can be read in
+                * the stream. If we rotated because we reached the end
+                * of a tracefile, it means the following tracefile
+                * needs to contain at least one index, else we would
+                * have already returned LTTNG_VIEWER_INDEX_RETRY to the
+                * viewer. The updated index_sent_seqcount needs to
+                * point to a readable index entry now.
+                *
+                * In the case where we "rotate" on a single file, we
+                * can end up in a case where the requested index is
+                * still unavailable.
                 */
-               read_ret = lttng_read(vstream->index_fd->fd, tmp, 1);
-               if (read_ret == 1) {
-                       off_t seek_ret;
-
-                       /* There is still data to read. Rewind position. */
-                       seek_ret = lseek(vstream->index_fd->fd, -1, SEEK_CUR);
-                       if (seek_ret < 0) {
-                               ret = -1;
-                               goto end;
-                       }
-                       ret = 0;
-               } else if (read_ret == 0) {
-                       /* EOF. We need to rotate. */
-                       DBG("Viewer stream %" PRIu64 " rotation due to EOF",
-                                       vstream->stream->stream_handle);
-                       ret = viewer_stream_rotate(vstream);
-                       if (ret < 0) {
-                               goto end;
-                       } else if (ret == 1) {
-                               /* EOF across entire stream. */
-                               index->status = htobe32(LTTNG_VIEWER_INDEX_HUP);
-                               goto hup;
-                       }
-                       assert(viewer_stream_is_tracefile_seq_readable(vstream,
-                               vstream->current_tracefile_seq));
-                       /* ret == 0 means successful so we continue. */
-                       ret = 0;
-               } else {
-                       /* Error reading index. */
-                       ret = -1;
+               if (rstream->tracefile_count == 1 &&
+                               !tracefile_array_seq_in_file(
+                                       rstream->tfa,
+                                       vstream->current_tracefile_id,
+                                       vstream->index_sent_seqcount)) {
+                       index->status = htobe32(LTTNG_VIEWER_INDEX_RETRY);
+                       goto index_ready;
                }
+               assert(tracefile_array_seq_in_file(rstream->tfa,
+                               vstream->current_tracefile_id,
+                               vstream->index_sent_seqcount));
        }
+       /* ret == 0 means successful so we continue. */
+       ret = 0;
 end:
        return ret;
 
@@ -1249,7 +1272,6 @@ static
 int viewer_get_next_index(struct relay_connection *conn)
 {
        int ret;
-       ssize_t read_ret;
        struct lttng_viewer_get_next_index request_index;
        struct lttng_viewer_index viewer_index;
        struct ctf_packet_index packet_index;
@@ -1273,8 +1295,10 @@ int viewer_get_next_index(struct relay_connection *conn)
 
        vstream = viewer_stream_get_by_id(be64toh(request_index.stream_id));
        if (!vstream) {
-               ret = -1;
-               goto end;
+               DBG("Client requested index of unknown stream id %" PRIu64,
+                               be64toh(request_index.stream_id));
+               viewer_index.status = htobe32(LTTNG_VIEWER_INDEX_ERR);
+               goto send_reply;
        }
 
        /* Use back. ref. Protected by refcounts. */
@@ -1370,16 +1394,15 @@ int viewer_get_next_index(struct relay_connection *conn)
                viewer_index.flags |= LTTNG_VIEWER_FLAG_NEW_STREAM;
        }
 
-       read_ret = lttng_read(vstream->index_fd->fd, &packet_index,
-                       sizeof(packet_index));
-       if (read_ret < sizeof(packet_index)) {
-               ERR("Relay reading index file %d returned %zd",
-                       vstream->index_fd->fd, read_ret);
+       ret = lttng_index_file_read(vstream->index_file, &packet_index);
+       if (ret) {
+               ERR("Relay error reading index file %d",
+                               vstream->index_file->fd);
                viewer_index.status = htobe32(LTTNG_VIEWER_INDEX_ERR);
                goto send_reply;
        } else {
                viewer_index.status = htobe32(LTTNG_VIEWER_INDEX_OK);
-               vstream->last_sent_index++;
+               vstream->index_sent_seqcount++;
        }
 
        /*
@@ -1397,7 +1420,9 @@ int viewer_get_next_index(struct relay_connection *conn)
        viewer_index.stream_id = packet_index.stream_id;
 
 send_reply:
-       pthread_mutex_unlock(&rstream->lock);
+       if (rstream) {
+               pthread_mutex_unlock(&rstream->lock);
+       }
 
        if (metadata_viewer_stream) {
                pthread_mutex_lock(&metadata_viewer_stream->stream->lock);
@@ -1422,9 +1447,11 @@ send_reply:
        }
        health_code_update();
 
-       DBG("Index %" PRIu64 " for stream %" PRIu64 " sent",
-                       vstream->last_sent_index,
-                       vstream->stream->stream_handle);
+       if (vstream) {
+               DBG("Index %" PRIu64 " for stream %" PRIu64 " sent",
+                               vstream->index_sent_seqcount,
+                               vstream->stream->stream_handle);
+       }
 end:
        if (metadata_viewer_stream) {
                viewer_stream_put(metadata_viewer_stream);
@@ -1458,8 +1485,6 @@ int viewer_get_packet(struct relay_connection *conn)
        struct lttng_viewer_get_packet get_packet_info;
        struct lttng_viewer_trace_packet reply;
        struct relay_viewer_stream *vstream = NULL;
-       struct ctf_trace *ctf_trace;
-       struct relay_viewer_stream *metadata_viewer_stream = NULL;
 
        DBG2("Relay get data packet");
 
@@ -1477,60 +1502,13 @@ int viewer_get_packet(struct relay_connection *conn)
 
        vstream = viewer_stream_get_by_id(be64toh(get_packet_info.stream_id));
        if (!vstream) {
-               goto error;
-       }
-
-       ctf_trace = vstream->stream->trace;
-
-       /* metadata_viewer_stream may be NULL. */
-       metadata_viewer_stream =
-                       ctf_trace_get_viewer_metadata_stream(ctf_trace);
-
-       if (metadata_viewer_stream) {
-               bool get_packet_err = false;
-
-               pthread_mutex_lock(&metadata_viewer_stream->stream->lock);
-               DBG("get packet metadata check: recv %" PRIu64 " sent %" PRIu64,
-                       metadata_viewer_stream->stream->metadata_received,
-                       metadata_viewer_stream->metadata_sent);
-               if (!metadata_viewer_stream->stream->metadata_received ||
-                               metadata_viewer_stream->stream->metadata_received >
-                                       metadata_viewer_stream->metadata_sent) {
-                       /*
-                        * We prevent the client from reading a data stream as
-                        * long as there is metadata left to consume. This
-                        * ensures that the client won't receive data of which
-                        * it can't make sense.
-                        */
-                       get_packet_err = true;
-               }
-               pthread_mutex_unlock(&metadata_viewer_stream->stream->lock);
-               viewer_stream_put(metadata_viewer_stream);
-               if (get_packet_err) {
-                       reply.status = htobe32(LTTNG_VIEWER_GET_PACKET_ERR);
-                       reply.flags |= LTTNG_VIEWER_FLAG_NEW_METADATA;
-                       goto send_reply_nolock;
-               }
+               DBG("Client requested packet of unknown stream id %" PRIu64,
+                               be64toh(get_packet_info.stream_id));
+               reply.status = htobe32(LTTNG_VIEWER_GET_PACKET_ERR);
+               goto send_reply_nolock;
        }
 
        pthread_mutex_lock(&vstream->stream->lock);
-       /*
-        * The vstream->stream_fd used here has been opened by
-        * get_next_index. It is opened there because this is what
-        * allows us to grab a reference to the file with stream lock
-        * held, thus protecting us against overwrite caused by
-        * tracefile rotation. Since tracefile rotation unlinks the old
-        * data file, we are ensured that we won't have our data
-        * overwritten under us.
-        */
-       ret = check_new_streams(conn);
-       if (ret < 0) {
-               goto end_free;
-       } else if (ret == 1) {
-               reply.status = htobe32(LTTNG_VIEWER_GET_PACKET_ERR);
-               reply.flags |= LTTNG_VIEWER_FLAG_NEW_STREAM;
-               goto send_reply;
-       }
 
        len = be32toh(get_packet_info.len);
        data = zmalloc(len);
@@ -1637,6 +1615,8 @@ int viewer_get_metadata(struct relay_connection *conn)
                 * Reply back to the client with an error if we cannot
                 * find it.
                 */
+               DBG("Client requested metadata of unknown stream id %" PRIu64,
+                               be64toh(request.stream_id));
                reply.status = htobe32(LTTNG_VIEWER_METADATA_ERR);
                goto send_reply;
        }
@@ -1770,6 +1750,78 @@ end:
        return ret;
 }
 
+/*
+ * Detach a viewer session.
+ *
+ * Return 0 on success or else a negative value.
+ */
+static
+int viewer_detach_session(struct relay_connection *conn)
+{
+       int ret;
+       struct lttng_viewer_detach_session_response response;
+       struct lttng_viewer_detach_session_request request;
+       struct relay_session *session = NULL;
+       uint64_t viewer_session_to_close;
+
+       DBG("Viewer detach session received");
+
+       assert(conn);
+
+       health_code_update();
+
+       /* Receive the request from the connected client. */
+       ret = recv_request(conn->sock, &request, sizeof(request));
+       if (ret < 0) {
+               goto end;
+       }
+       viewer_session_to_close = be64toh(request.session_id);
+
+       if (!conn->viewer_session) {
+               DBG("Client trying to detach before creating a live viewer session");
+               response.status = htobe32(LTTNG_VIEWER_DETACH_SESSION_ERR);
+               goto send_reply;
+       }
+
+       health_code_update();
+
+       memset(&response, 0, sizeof(response));
+       DBG("Detaching from session ID %" PRIu64, viewer_session_to_close);
+
+       session = session_get_by_id(be64toh(request.session_id));
+       if (!session) {
+               DBG("Relay session %" PRIu64 " not found",
+                               be64toh(request.session_id));
+               response.status = htobe32(LTTNG_VIEWER_DETACH_SESSION_UNK);
+               goto send_reply;
+       }
+
+       ret = viewer_session_is_attached(conn->viewer_session, session);
+       if (ret != 1) {
+               DBG("Not attached to this session");
+               response.status = htobe32(LTTNG_VIEWER_DETACH_SESSION_ERR);
+               goto send_reply_put;
+       }
+
+       viewer_session_close_one_session(conn->viewer_session, session);
+       response.status = htobe32(LTTNG_VIEWER_DETACH_SESSION_OK);
+       DBG("Session %" PRIu64 " detached.", viewer_session_to_close);
+
+send_reply_put:
+       session_put(session);
+
+send_reply:
+       health_code_update();
+       ret = send_response(conn->sock, &response, sizeof(response));
+       if (ret < 0) {
+               goto end;
+       }
+       health_code_update();
+       ret = 0;
+
+end:
+       return ret;
+}
 
 /*
  * live_relay_unknown_command: send -1 if received unknown command
@@ -1831,6 +1883,9 @@ int process_control(struct lttng_viewer_cmd *recv_hdr,
        case LTTNG_VIEWER_CREATE_SESSION:
                ret = viewer_create_session(conn);
                break;
+       case LTTNG_VIEWER_DETACH_SESSION:
+               ret = viewer_detach_session(conn);
+               break;
        default:
                ERR("Received unknown viewer command (%u)",
                                be32toh(recv_hdr->cmd));
@@ -1945,10 +2000,7 @@ restart:
 
                        /* Inspect the relay conn pipe for new connection. */
                        if (pollfd == live_conn_pipe[0]) {
-                               if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
-                                       ERR("Relay live pipe error");
-                                       goto error;
-                               } else if (revents & LPOLLIN) {
+                               if (revents & LPOLLIN) {
                                        struct relay_connection *conn;
 
                                        ret = lttng_read(live_conn_pipe[0],
@@ -1960,6 +2012,12 @@ restart:
                                                        LPOLLIN | LPOLLRDHUP);
                                        connection_ht_add(viewer_connections_ht, conn);
                                        DBG("Connection socket %d added to poll", conn->sock->fd);
+                               } else if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
+                                       ERR("Relay live pipe error");
+                                       goto error;
+                               } else {
+                                       ERR("Unexpected poll events %u for sock %d", revents, pollfd);
+                                       goto error;
                                }
                        } else {
                                /* Connection activity. */
@@ -1970,11 +2028,7 @@ restart:
                                        continue;
                                }
 
-                               if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
-                                       cleanup_connection_pollfd(&events, pollfd);
-                                       /* Put "create" ownership reference. */
-                                       connection_put(conn);
-                               } else if (revents & LPOLLIN) {
+                               if (revents & LPOLLIN) {
                                        ret = conn->sock->ops->recvmsg(conn->sock, &recv_hdr,
                                                        sizeof(recv_hdr), 0);
                                        if (ret <= 0) {
@@ -1993,6 +2047,14 @@ restart:
                                                        DBG("Viewer connection closed with %d", pollfd);
                                                }
                                        }
+                               } else if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
+                                       cleanup_connection_pollfd(&events, pollfd);
+                                       /* Put "create" ownership reference. */
+                                       connection_put(conn);
+                               } else {
+                                       ERR("Unexpected poll events %u for sock %d", revents, pollfd);
+                                       connection_put(conn);
+                                       goto error;
                                }
                                /* Put local "get_by_sock" reference. */
                                connection_put(conn);
@@ -2117,7 +2179,7 @@ int relayd_live_create(struct lttng_uri *uri)
        }
 
        /* Setup the dispatcher thread */
-       ret = pthread_create(&live_dispatcher_thread, NULL,
+       ret = pthread_create(&live_dispatcher_thread, default_pthread_attr(),
                        thread_dispatcher, (void *) NULL);
        if (ret) {
                errno = ret;
@@ -2127,7 +2189,7 @@ int relayd_live_create(struct lttng_uri *uri)
        }
 
        /* Setup the worker thread */
-       ret = pthread_create(&live_worker_thread, NULL,
+       ret = pthread_create(&live_worker_thread, default_pthread_attr(),
                        thread_worker, NULL);
        if (ret) {
                errno = ret;
@@ -2137,7 +2199,7 @@ int relayd_live_create(struct lttng_uri *uri)
        }
 
        /* Setup the listener thread */
-       ret = pthread_create(&live_listener_thread, NULL,
+       ret = pthread_create(&live_listener_thread, default_pthread_attr(),
                        thread_listener, (void *) NULL);
        if (ret) {
                errno = ret;
This page took 0.03171 seconds and 4 git commands to generate.