notification: fetch capture payload on notification reception
authorJonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Mon, 8 Mar 2021 20:59:01 +0000 (15:59 -0500)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Tue, 16 Mar 2021 15:23:57 +0000 (11:23 -0400)
Signed-off-by: Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
Change-Id: Id52749b59969276b5390f4494df48940662d5d8c

src/bin/lttng-sessiond/notification-thread-commands.c
src/bin/lttng-sessiond/notification-thread-events.c
src/bin/lttng-sessiond/notification-thread-internal.h

index 44bee3d3ba6f634e4fe14db72db3e612ead6a5d6..b1b33343ba5da6ec663a981d944e70f9256861c6 100644 (file)
@@ -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);
 }
index 309c54c879cc0cd14cae470a61af8c9dad1ffe06..7fea927d8ba57015e5d5a228383ab0aec4f4de07 100644 (file)
@@ -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;
        }
 
index 0403527dca1f4f5b67d0f25cbe0cb91efee27eda..e6467dc27cb107695f4445888ee52f8abf0d27fd 100644 (file)
@@ -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(
This page took 0.029918 seconds and 4 git commands to generate.