X-Git-Url: https://git.liburcu.org/?a=blobdiff_plain;f=src%2Fbin%2Flttng-relayd%2Fmain.c;h=d2e78345a7f17e878c0dfe5715f289b431d398c8;hb=90d4cb3a9a09396e8d26214bf6826fa3f89f93f3;hp=8415e8cef106db18395a2666c79b555b68d418df;hpb=ab5be9fa2eb5ba9600a82cd18fd3cfcbac69169a;p=lttng-tools.git diff --git a/src/bin/lttng-relayd/main.c b/src/bin/lttng-relayd/main.c index 8415e8cef..d2e78345a 100644 --- a/src/bin/lttng-relayd/main.c +++ b/src/bin/lttng-relayd/main.c @@ -230,7 +230,7 @@ static int set_option(int opt, const char *arg, const char *optname) errno = 0; v = strtoul(arg, NULL, 0); - if (errno != 0 || !isdigit(arg[0])) { + if (errno != 0 || !isdigit((unsigned char) arg[0])) { ERR("Wrong value in --fd-pool-size parameter: %s", arg); ret = -1; goto end; @@ -507,7 +507,7 @@ static int set_fd_pool_size(void) goto end; } - DBG("File descriptor pool size argument (%u) adjusted to %u to accomodate transient fd uses", + DBG("File descriptor pool size argument (%u) adjusted to %u to accommodates transient fd uses", lttng_opt_fd_pool_size, lttng_opt_fd_pool_size - DEFAULT_RELAYD_FD_POOL_SIZE_RESERVE); lttng_opt_fd_pool_size -= DEFAULT_RELAYD_FD_POOL_SIZE_RESERVE; @@ -918,6 +918,10 @@ static int create_named_thread_poll_set(struct lttng_poll_event *events, ret = fd_tracker_util_poll_create(the_fd_tracker, name, events, 1, LTTNG_CLOEXEC); + if (ret) { + PERROR("Failed to create \"%s\" poll file descriptor", name); + goto error; + } /* Add quit pipe */ ret = lttng_poll_add(events, thread_quit_pipe[0], LPOLLIN | LPOLLERR); @@ -1018,7 +1022,11 @@ static struct lttcomm_sock *relay_socket_create(struct lttng_uri *uri, ret = fd_tracker_open_unsuspendable_fd(the_fd_tracker, &sock_fd, (const char **) (formated_name ? &formated_name : NULL), 1, create_sock, sock); - free(formated_name); + if (ret) { + PERROR("Failed to open \"%s\" relay socket", + formated_name ?: "Unknown"); + goto error; + } DBG("Listening on %s socket %d", name, sock->fd); ret = sock->ops->bind(sock); @@ -1033,12 +1041,14 @@ static struct lttcomm_sock *relay_socket_create(struct lttng_uri *uri, } + free(formated_name); return sock; error: if (sock) { lttcomm_destroy_sock(sock); } + free(formated_name); return NULL; } @@ -1075,6 +1085,7 @@ static void *relay_thread_listener(void *data) DBG("[thread] Relay listener started"); + rcu_register_thread(); health_register(health_relayd, HEALTH_RELAYD_TYPE_LISTENER); health_code_update(); @@ -1258,6 +1269,7 @@ error_sock_control: ERR("Health error occurred in %s", __func__); } health_unregister(health_relayd); + rcu_unregister_thread(); DBG("Relay listener thread cleanup complete"); lttng_relay_stop_threads(); return NULL; @@ -1620,7 +1632,8 @@ static int relay_add_stream(const struct lttcomm_relayd_hdr *recv_hdr, group_by_session_path_name = backward_compat_group_by_session( path_name, - session->session_name); + session->session_name, + session->creation_time.value); if (!group_by_session_path_name) { ERR("Failed to apply group by session to stream of session %" PRIu64, session->id); @@ -1735,24 +1748,6 @@ static int relay_close_stream(const struct lttcomm_relayd_hdr *recv_hdr, * request. */ try_stream_close(stream); - if (stream->is_metadata) { - struct relay_viewer_stream *vstream; - - vstream = viewer_stream_get_by_id(stream->stream_handle); - if (vstream) { - if (stream->no_new_metadata_notified) { - /* - * Since all the metadata has been sent to the - * viewer and that we have a request to close - * its stream, we can safely teardown the - * corresponding metadata viewer stream. - */ - viewer_stream_put(vstream); - } - /* Put local reference. */ - viewer_stream_put(vstream); - } - } stream_put(stream); ret = 0; @@ -2490,6 +2485,125 @@ end_no_session: return ret; } +static ssize_t relay_unpack_rotate_streams_header( + const struct lttng_buffer_view *payload, + struct lttcomm_relayd_rotate_streams *_rotate_streams) +{ + struct lttcomm_relayd_rotate_streams rotate_streams; + /* + * Set to the smallest version (packed) of `lttcomm_relayd_rotate_streams`. + * This is the smallest version of this structure, but it can be larger; + * this variable is updated once the proper size of the structure is known. + * + * See comment at the declaration of this structure for more information. + */ + ssize_t header_len = sizeof(struct lttcomm_relayd_rotate_streams_packed); + size_t expected_payload_size_no_padding, + expected_payload_size_3_bytes_padding, + expected_payload_size_7_bytes_padding; + + if (payload->size < header_len) { + ERR("Unexpected payload size in \"relay_rotate_session_stream\": expected >= %zu bytes, got %zu bytes", + header_len, payload->size); + goto error; + } + + /* + * Some versions incorrectly omitted the LTTNG_PACKED annotation on the + * `new_chunk_id` optional field of struct lttcomm_relayd_rotate_streams. + * + * We start by "unpacking" `stream_count` to figure out the padding length + * emited by our peer. + */ + memcpy(&rotate_streams.stream_count, payload->data, + sizeof(rotate_streams.stream_count)); + rotate_streams = (typeof(rotate_streams)) { + .stream_count = be32toh(rotate_streams.stream_count), + }; + + /* + * Payload size expected given the possible padding lengths in + * `struct lttcomm_relayd_rotate_streams`. + */ + expected_payload_size_no_padding = (rotate_streams.stream_count * + sizeof(*rotate_streams.rotation_positions)) + + sizeof(struct lttcomm_relayd_rotate_streams_packed); + expected_payload_size_3_bytes_padding = (rotate_streams.stream_count * + sizeof(*rotate_streams.rotation_positions)) + + sizeof(struct lttcomm_relayd_rotate_streams_3_bytes_padding); + expected_payload_size_7_bytes_padding = (rotate_streams.stream_count * + sizeof(*rotate_streams.rotation_positions)) + + sizeof(struct lttcomm_relayd_rotate_streams_7_bytes_padding); + + if (payload->size == expected_payload_size_no_padding) { + struct lttcomm_relayd_rotate_streams_packed packed_rotate_streams; + + /* + * This handles cases where someone might build with + * -fpack-struct or any other toolchain that wouldn't produce + * padding to align `value`. + */ + DBG("Received `struct lttcomm_relayd_rotate_streams` with no padding"); + + header_len = sizeof(packed_rotate_streams); + memcpy(&packed_rotate_streams, payload->data, header_len); + + /* Unpack the packed structure to the natively-packed version. */ + *_rotate_streams = (typeof(*_rotate_streams)) { + .stream_count = be32toh(packed_rotate_streams.stream_count), + .new_chunk_id = (typeof(_rotate_streams->new_chunk_id)) { + .is_set = !!packed_rotate_streams.new_chunk_id.is_set, + .value = be64toh(packed_rotate_streams.new_chunk_id.value), + } + }; + } else if (payload->size == expected_payload_size_3_bytes_padding) { + struct lttcomm_relayd_rotate_streams_3_bytes_padding padded_rotate_streams; + + DBG("Received `struct lttcomm_relayd_rotate_streams` with 3 bytes of padding (4-byte aligned peer)"); + + header_len = sizeof(padded_rotate_streams); + memcpy(&padded_rotate_streams, payload->data, header_len); + + /* Unpack the 3-byte padded structure to the natively-packed version. */ + *_rotate_streams = (typeof(*_rotate_streams)) { + .stream_count = be32toh(padded_rotate_streams.stream_count), + .new_chunk_id = (typeof(_rotate_streams->new_chunk_id)) { + .is_set = !!padded_rotate_streams.new_chunk_id.is_set, + .value = be64toh(padded_rotate_streams.new_chunk_id.value), + } + }; + } else if (payload->size == expected_payload_size_7_bytes_padding) { + struct lttcomm_relayd_rotate_streams_7_bytes_padding padded_rotate_streams; + + DBG("Received `struct lttcomm_relayd_rotate_streams` with 7 bytes of padding (8-byte aligned peer)"); + + header_len = sizeof(padded_rotate_streams); + memcpy(&padded_rotate_streams, payload->data, header_len); + + /* Unpack the 7-byte padded structure to the natively-packed version. */ + *_rotate_streams = (typeof(*_rotate_streams)) { + .stream_count = be32toh(padded_rotate_streams.stream_count), + .new_chunk_id = (typeof(_rotate_streams->new_chunk_id)) { + .is_set = !!padded_rotate_streams.new_chunk_id.is_set, + .value = be64toh(padded_rotate_streams.new_chunk_id.value), + } + }; + + header_len = sizeof(padded_rotate_streams); + } else { + ERR("Unexpected payload size in \"relay_rotate_session_stream\": expected %zu, %zu or %zu bytes, got %zu bytes", + expected_payload_size_no_padding, + expected_payload_size_3_bytes_padding, + expected_payload_size_7_bytes_padding, + payload->size); + goto error; + } + + return header_len; +error: + return -1; +} + /* * relay_rotate_session_stream: rotate a stream to a new tracefile for the * session rotation feature (not the tracefile rotation feature). @@ -2507,11 +2621,11 @@ static int relay_rotate_session_streams( struct lttcomm_relayd_rotate_streams rotate_streams; struct lttcomm_relayd_generic_reply reply = {}; struct relay_stream *stream = NULL; - const size_t header_len = sizeof(struct lttcomm_relayd_rotate_streams); struct lttng_trace_chunk *next_trace_chunk = NULL; struct lttng_buffer_view stream_positions; char chunk_id_buf[MAX_INT_DEC_LEN(uint64_t)]; const char *chunk_id_str = "none"; + ssize_t header_len; if (!session || !conn->version_check_done) { ERR("Trying to rotate a stream before version check"); @@ -2525,24 +2639,12 @@ static int relay_rotate_session_streams( goto end_no_reply; } - if (payload->size < header_len) { - ERR("Unexpected payload size in \"relay_rotate_session_stream\": expected >= %zu bytes, got %zu bytes", - header_len, payload->size); + header_len = relay_unpack_rotate_streams_header(payload, &rotate_streams); + if (header_len < 0) { ret = -1; goto end_no_reply; } - memcpy(&rotate_streams, payload->data, header_len); - - /* Convert header to host endianness. */ - rotate_streams = (typeof(rotate_streams)) { - .stream_count = be32toh(rotate_streams.stream_count), - .new_chunk_id = (typeof(rotate_streams.new_chunk_id)) { - .is_set = !!rotate_streams.new_chunk_id.is_set, - .value = be64toh(rotate_streams.new_chunk_id.value), - } - }; - if (rotate_streams.new_chunk_id.is_set) { /* * Retrieve the trace chunk the stream must transition to. As @@ -2580,7 +2682,7 @@ static int relay_rotate_session_streams( chunk_id_str); stream_positions = lttng_buffer_view_from_view(payload, - sizeof(rotate_streams), -1); + header_len, -1); if (!stream_positions.data || stream_positions.size < (rotate_streams.stream_count * @@ -2639,8 +2741,6 @@ end_no_reply: return ret; } - - /* * relay_create_trace_chunk: create a new trace chunk */ @@ -2932,7 +3032,7 @@ static int relay_close_trace_chunk(const struct lttcomm_relayd_hdr *recv_hdr, new_path); if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) { ret = -1; - goto end; + goto end_unlock_session; } session->ongoing_rotation = false; } @@ -2950,7 +3050,7 @@ static int relay_close_trace_chunk(const struct lttcomm_relayd_hdr *recv_hdr, chunk_status = lttng_trace_chunk_rename_path(chunk, old_path); if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) { ret = -1; - goto end; + goto end_unlock_session; } } chunk_status = lttng_trace_chunk_set_close_timestamp(