From: Jonathan Rajotte Date: Mon, 8 Mar 2021 20:59:01 +0000 (-0500) Subject: notification: fetch capture payload on notification reception X-Git-Tag: v2.13.0-rc1~234 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=82b3cbf431e12b5c5f65eaa474d0328fb86ece87;p=lttng-tools.git notification: fetch capture payload on notification reception Signed-off-by: Jonathan Rajotte Signed-off-by: Jérémie Galarneau Change-Id: Id52749b59969276b5390f4494df48940662d5d8c --- diff --git a/src/bin/lttng-sessiond/notification-thread-commands.c b/src/bin/lttng-sessiond/notification-thread-commands.c index 44bee3d3b..b1b33343b 100644 --- a/src/bin/lttng-sessiond/notification-thread-commands.c +++ b/src/bin/lttng-sessiond/notification-thread-commands.c @@ -382,17 +382,22 @@ int notification_thread_client_communication_update( return run_command_no_wait(handle, &cmd); } +/* + * Takes ownership of the payload if present. + */ LTTNG_HIDDEN -struct lttng_event_notifier_notification * -lttng_event_notifier_notification_create(uint64_t tracer_token, - enum lttng_domain_type domain) +struct lttng_event_notifier_notification *lttng_event_notifier_notification_create( + uint64_t tracer_token, + enum lttng_domain_type domain, + char *payload, + size_t payload_size) { struct lttng_event_notifier_notification *notification = NULL; assert(domain != LTTNG_DOMAIN_NONE); + assert((payload && payload_size) || (!payload && !payload_size)); - notification = zmalloc( - sizeof(struct lttng_event_notifier_notification)); + notification = zmalloc(sizeof(struct lttng_event_notifier_notification)); if (notification == NULL) { ERR("[notification-thread] Error allocating notification"); goto end; @@ -400,6 +405,8 @@ lttng_event_notifier_notification_create(uint64_t tracer_token, notification->tracer_token = tracer_token; notification->type = domain; + notification->capture_buffer = payload; + notification->capture_buf_size = payload_size; end: return notification; @@ -413,5 +420,6 @@ void lttng_event_notifier_notification_destroy( return; } + free(notification->capture_buffer); free(notification); } diff --git a/src/bin/lttng-sessiond/notification-thread-events.c b/src/bin/lttng-sessiond/notification-thread-events.c index 309c54c87..7fea927d8 100644 --- a/src/bin/lttng-sessiond/notification-thread-events.c +++ b/src/bin/lttng-sessiond/notification-thread-events.c @@ -48,6 +48,9 @@ #define CLIENT_POLL_MASK_IN (LPOLLIN | LPOLLERR | LPOLLHUP | LPOLLRDHUP) #define CLIENT_POLL_MASK_IN_OUT (CLIENT_POLL_MASK_IN | LPOLLOUT) +/* The tracers currently limit the capture size to PIPE_BUF (4kb on linux). */ +#define MAX_CAPTURE_SIZE (PIPE_BUF) + enum lttng_object_type { LTTNG_OBJECT_TYPE_UNKNOWN, LTTNG_OBJECT_TYPE_NONE, @@ -4244,6 +4247,8 @@ struct lttng_event_notifier_notification *recv_one_event_notifier_notification( int ret; uint64_t token; struct lttng_event_notifier_notification *notification = NULL; + char *capture_buffer = NULL; + size_t capture_buffer_size; void *reception_buffer; size_t reception_size; @@ -4280,17 +4285,55 @@ struct lttng_event_notifier_notification *recv_one_event_notifier_notification( switch(domain) { case LTTNG_DOMAIN_UST: token = ust_notification.token; + capture_buffer_size = ust_notification.capture_buf_size; break; case LTTNG_DOMAIN_KERNEL: token = kernel_notification.token; + capture_buffer_size = 0; break; default: abort(); } - notification = lttng_event_notifier_notification_create( - token, domain); + if (capture_buffer_size == 0) { + capture_buffer = NULL; + goto skip_capture; + } + + if (capture_buffer_size > MAX_CAPTURE_SIZE) { + ERR("[notification-thread] Event notifier has a capture payload size which exceeds the maximum allowed size: capture_payload_size = %zu bytes, max allowed size = %d bytes", + capture_buffer_size, MAX_CAPTURE_SIZE); + goto end; + } + + capture_buffer = zmalloc(capture_buffer_size); + if (!capture_buffer) { + ERR("[notification-thread] Failed to allocate capture buffer"); + goto end; + } + + /* Fetch additional payload (capture). */ + ret = lttng_read(notification_pipe_read_fd, capture_buffer, capture_buffer_size); + if (ret != capture_buffer_size) { + ERR("[notification-thread] Failed to read from event source pipe (fd = %i)", + notification_pipe_read_fd); + goto end; + } + +skip_capture: + notification = lttng_event_notifier_notification_create(token, domain, + capture_buffer, capture_buffer_size); + if (notification == NULL) { + goto end; + } + + /* + * Ownership transfered to the lttng_event_notifier_notification object. + */ + capture_buffer = NULL; + end: + free(capture_buffer); return notification; } @@ -4425,14 +4468,14 @@ int handle_one_event_notifier_notification( struct notification_thread_state *state, int pipe, enum lttng_domain_type domain) { - int ret; + int ret = 0; struct lttng_event_notifier_notification *notification = NULL; notification = recv_one_event_notifier_notification(pipe, domain); if (notification == NULL) { + /* Reception failed, don't consider it fatal. */ ERR("[notification-thread] Error receiving an event notifier notification from tracer: fd = %i, domain = %s", pipe, lttng_domain_type_str(domain)); - ret = -1; goto end; } diff --git a/src/bin/lttng-sessiond/notification-thread-internal.h b/src/bin/lttng-sessiond/notification-thread-internal.h index 0403527dc..e6467dc27 100644 --- a/src/bin/lttng-sessiond/notification-thread-internal.h +++ b/src/bin/lttng-sessiond/notification-thread-internal.h @@ -82,6 +82,8 @@ struct channel_info { struct lttng_event_notifier_notification { uint64_t tracer_token; enum lttng_domain_type type; + size_t capture_buf_size; + char *capture_buffer; }; struct notification_client_list_element { @@ -248,10 +250,15 @@ int notification_thread_client_communication_update( notification_client_id id, enum client_transmission_status transmission_status); +/* + * Takes ownership of the payload if present. + */ LTTNG_HIDDEN struct lttng_event_notifier_notification *lttng_event_notifier_notification_create( uint64_t tracer_token, - enum lttng_domain_type domain); + enum lttng_domain_type domain, + char *payload, + size_t payload_size); LTTNG_HIDDEN void lttng_event_notifier_notification_destroy(