payload: use fd_handle instead of raw file descriptors
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Wed, 22 Jul 2020 20:15:44 +0000 (16:15 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Mon, 27 Jul 2020 20:31:58 +0000 (16:31 -0400)
Using raw file descriptors with lttng_payloads introduces scary file
descriptor corner-cases when mixing with asynchroneous communication and
lttng_payloads.

Since an lttng_payload doesn't own its file descriptors, attempting it
is easy to fall into a situation where a file descriptor is referenced
by an lttng_payload while the owner is destroyed.

For instance, a userspace probe could be destroyed while its description
is waiting to be sent to a client.

The various use sites of the payload/payload_view APIs are adjusted.

Utilities to send/recv fds through unix sockets using the payload and
payload view interfaces are added as part of this commit as they use
the payload's fd_handles.

Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
Change-Id: I44073f1b683af6c475e8e93c25a76910acf955e4

13 files changed:
include/lttng/userspace-probe-internal.h
include/lttng/userspace-probe.h
src/bin/lttng-sessiond/client.c
src/common/fd-handle.c
src/common/payload-view.c
src/common/payload-view.h
src/common/payload.c
src/common/payload.h
src/common/unix.c
src/common/unix.h
src/common/userspace-probe.c
src/lib/lttng-ctl/lttng-ctl.c
tests/unit/test_payload.c

index d9e5de254c6937cae82495c5e7a15a837b46476f..ffe3f1cf9e087ad062ff1495536bac4800fa5577 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <lttng/userspace-probe.h>
 #include <common/macros.h>
+#include <common/fd-handle.h>
 #include <stdbool.h>
 
 struct lttng_payload;
@@ -97,9 +98,8 @@ struct lttng_userspace_probe_location_function {
         * binary_fd is a file descriptor to the executable file. It's open
         * early on to keep the backing inode valid over the course of the
         * intrumentation and use. It prevents deletion and reuse races.
-        * Set to -1 if not open.
         */
-       int binary_fd;
+       struct fd_handle *binary_fd;
        enum lttng_userspace_probe_location_function_instrumentation_type instrumentation_type;
 };
 
@@ -112,9 +112,8 @@ struct lttng_userspace_probe_location_tracepoint {
         * binary_fd is a file descriptor to the executable file. It's open
         * early on to keep the backing inode valid over the course of the
         * intrumentation and use. It prevents deletion and reuse races.
-        * Set to -1 if not open.
         */
-       int binary_fd;
+       struct fd_handle *binary_fd;
 };
 
 LTTNG_HIDDEN
@@ -127,14 +126,6 @@ int lttng_userspace_probe_location_create_from_payload(
                struct lttng_payload_view *view,
                struct lttng_userspace_probe_location **probe_location);
 
-LTTNG_HIDDEN
-int lttng_userspace_probe_location_function_set_binary_fd(
-               struct lttng_userspace_probe_location *location, int binary_fd);
-
-LTTNG_HIDDEN
-int lttng_userspace_probe_location_tracepoint_set_binary_fd(
-               struct lttng_userspace_probe_location *location, int binary_fd);
-
 /*
  * Returns a version of the location that is serialized to a contiguous region
  * of memory. Pass NULL to buffer to only get the storage requirement of the
index 7215bd9679303e0fba793647f9d17d6473679529..5a6fa51a0318d8d1cf07e30d36692ea463bb1ab2 100644 (file)
@@ -120,7 +120,7 @@ extern const char *lttng_userspace_probe_location_function_get_function_name(
 
 /*
  * Get the FD to the target binary file to the probe location of the function
- * type.
+ * type. The FD is only valid for the duration of the lifetime of `location`.
  */
 extern int lttng_userspace_probe_location_function_get_binary_fd(
                const struct lttng_userspace_probe_location *location);
@@ -191,7 +191,7 @@ extern const char *lttng_userspace_probe_location_tracepoint_get_provider_name(
 
 /*
  * Get the FD to the target binary file to the probe location of the tracepoint
- * type.
+ * type. The FD is only valid for the duration of the lifetime of `location`.
  */
 extern int lttng_userspace_probe_location_tracepoint_get_binary_fd(
                const struct lttng_userspace_probe_location *location);
index 74bbbe9b2e05e3be7f94a1cba1330aae6d7658ba..1bf55f60b7f415afa81274b20af8c54bc09ef9d6 100644 (file)
@@ -13,6 +13,7 @@
 #include "common/dynamic-array.h"
 #include "common/payload.h"
 #include "common/payload-view.h"
+#include "common/fd-handle.h"
 #include "common/sessiond-comm/sessiond-comm.h"
 #include "common/payload.h"
 #include "common/payload-view.h"
@@ -92,7 +93,7 @@ static int setup_lttng_msg(struct command_ctx *cmd_ctx,
        };
 
        lttng_dynamic_buffer_set_size(&cmd_ctx->reply_payload.buffer, 0);
-       lttng_dynamic_array_clear(&cmd_ctx->reply_payload._fds);
+       lttng_dynamic_pointer_array_clear(&cmd_ctx->reply_payload._fd_handles);
 
        cmd_ctx->lttng_msg_size = total_msg_size;
 
@@ -592,9 +593,10 @@ static unsigned int lttng_sessions_count(uid_t uid, gid_t gid)
 static int receive_userspace_probe(struct command_ctx *cmd_ctx, int sock,
                int *sock_error, struct lttng_event *event)
 {
-       int fd, ret;
+       int fd = -1, ret;
        struct lttng_userspace_probe_location *probe_location;
        struct lttng_payload probe_location_payload;
+       struct fd_handle *handle = NULL;
 
        /*
         * Create a payload to store the serialized version of the probe
@@ -633,13 +635,25 @@ static int receive_userspace_probe(struct command_ctx *cmd_ctx, int sock,
                goto error;
        }
 
-       ret = lttng_payload_push_fd(&probe_location_payload, fd);
+       handle = fd_handle_create(fd);
+       if (!handle) {
+               ret = LTTNG_ERR_NOMEM;
+               goto error;
+       }
+
+       /* Transferred to the handle. */
+       fd = -1;
+
+       ret = lttng_payload_push_fd_handle(&probe_location_payload, handle);
        if (ret) {
                ERR("Failed to add userspace probe file descriptor to payload");
                ret = LTTNG_ERR_NOMEM;
                goto error;
        }
 
+       fd_handle_put(handle);
+       handle = NULL;
+
        {
                struct lttng_payload_view view = lttng_payload_view_from_payload(
                        &probe_location_payload, 0, -1);
@@ -662,6 +676,13 @@ static int receive_userspace_probe(struct command_ctx *cmd_ctx, int sock,
        }
 
 error:
+       if (fd >= 0) {
+               if (close(fd)) {
+                       PERROR("Failed to close userspace probe location binary fd");
+               }
+       }
+
+       fd_handle_put(handle);
        lttng_payload_reset(&probe_location_payload);
        return ret;
 }
@@ -699,6 +720,7 @@ static int check_rotate_compatible(void)
 static int send_unix_sock(int sock, struct lttng_payload_view *view)
 {
        int ret;
+       const int fd_count = lttng_payload_view_get_fd_handle_count(view);
 
        /* Check valid length */
        if (view->buffer.size == 0) {
@@ -712,10 +734,33 @@ static int send_unix_sock(int sock, struct lttng_payload_view *view)
                goto end;
        }
 
-       if (lttng_dynamic_array_get_count(&view->_fds) > 0) {
+       if (fd_count > 0) {
+               int i;
+               struct lttng_dynamic_array raw_fds;
+
+               /*
+                * Never holds ownership of the FDs; this is just used
+                * to put the FDs in a contiguous array.
+                */
+               lttng_dynamic_array_init(&raw_fds, sizeof(int), NULL);
+
+               for (i = 0; i < fd_count; i++) {
+                       struct fd_handle *handle =
+                               lttng_payload_view_pop_fd_handle(view);
+                       const int raw_fd = fd_handle_get_fd(handle);
+
+                       ret = lttng_dynamic_array_add_element(&raw_fds, &raw_fd);
+                       fd_handle_put(handle);
+                       if (ret) {
+                               lttng_dynamic_array_reset(&raw_fds);
+                               goto end;
+                       }
+               }
+
                ret = lttcomm_send_fds_unix_sock(sock,
-                               (const int *) view->_fds.buffer.data,
-                               lttng_dynamic_array_get_count(&view->_fds));
+                               (const int *) raw_fds.buffer.data,
+                               fd_count);
+               lttng_dynamic_array_reset(&raw_fds);
        }
 
 end:
@@ -2266,8 +2311,7 @@ static void *thread_manage_clients(void *data)
                        .gid = UINT32_MAX,
                };
                cmd_ctx.session = NULL;
-               lttng_dynamic_buffer_set_size(&cmd_ctx.reply_payload.buffer, 0);
-               lttng_dynamic_array_clear(&cmd_ctx.reply_payload._fds);
+               lttng_payload_clear(&cmd_ctx.reply_payload);
                cmd_ctx.lttng_msg_size = 0;
 
                DBG("Accepting client command ...");
@@ -2410,7 +2454,7 @@ static void *thread_manage_clients(void *data)
                               sizeof(llm));
                        assert(cmd_ctx.lttng_msg_size == cmd_ctx.reply_payload.buffer.size);
 
-                       llm->fd_count = lttng_payload_view_get_fd_count(&view);
+                       llm->fd_count = lttng_payload_view_get_fd_handle_count(&view);
 
                        DBG("Sending response (size: %d, retcode: %s (%d))",
                                        cmd_ctx.lttng_msg_size,
index a9c7be4a938ab86aa44d3c6316c3ccd8a04e6537..ddf70afadea98fa9a1aa4414bcee74a73e4c7c1a 100644 (file)
@@ -58,14 +58,20 @@ end:
 LTTNG_HIDDEN
 void fd_handle_get(struct fd_handle *handle)
 {
-       assert(handle);
+       if (!handle) {
+               return;
+       }
+
        urcu_ref_get(&handle->ref);
 }
 
 LTTNG_HIDDEN
 void fd_handle_put(struct fd_handle *handle)
 {
-       assert(handle);
+       if (!handle) {
+               return;
+       }
+
        urcu_ref_put(&handle->ref, fd_handle_release);
 }
 
index 8c99c56efa5d9d122c8fb6571e887cf3c74469cd..43ddf3132c774ed414292f7044ccf83b85a4ca04 100644 (file)
@@ -19,7 +19,7 @@ struct lttng_payload_view lttng_payload_view_from_payload(
        return (struct lttng_payload_view) {
                .buffer = lttng_buffer_view_from_dynamic_buffer(
                        &payload->buffer, offset, len),
-               ._fds = payload->_fds,
+               ._fd_handles = payload->_fd_handles,
        };
 }
 
@@ -31,9 +31,9 @@ struct lttng_payload_view lttng_payload_view_from_view(
        return (struct lttng_payload_view) {
                .buffer = lttng_buffer_view_from_view(
                                &view->buffer, offset, len),
-               ._fds = view->_fds,
-               ._iterator.p_fds_position = view->_iterator.p_fds_position ?:
-                               &view->_iterator.fds_position,
+               ._fd_handles = view->_fd_handles,
+               ._iterator.p_fd_handles_position = view->_iterator.p_fd_handles_position ?:
+                               &view->_iterator.fd_handles_position,
        };
 }
 
@@ -70,7 +70,7 @@ struct lttng_payload_view lttng_payload_view_init_from_buffer(
 }
 
 LTTNG_HIDDEN
-int lttng_payload_view_get_fd_count(struct lttng_payload_view *payload_view)
+int lttng_payload_view_get_fd_handle_count(struct lttng_payload_view *payload_view)
 {
        int ret;
        size_t position;
@@ -80,43 +80,43 @@ int lttng_payload_view_get_fd_count(struct lttng_payload_view *payload_view)
                goto end;
        }
 
-       ret = lttng_dynamic_array_get_count(&payload_view->_fds);
+       ret = lttng_dynamic_pointer_array_get_count(&payload_view->_fd_handles);
        if (ret < 0) {
                goto end;
        }
 
-       position = payload_view->_iterator.p_fds_position ?
-                       *payload_view->_iterator.p_fds_position :
-                       payload_view->_iterator.fds_position;
+       position = payload_view->_iterator.p_fd_handles_position ?
+                       *payload_view->_iterator.p_fd_handles_position :
+                       payload_view->_iterator.fd_handles_position;
        ret = ret - (int) position;
 end:
        return ret;
 }
 
 LTTNG_HIDDEN
-int lttng_payload_view_pop_fd(struct lttng_payload_view *view)
+struct fd_handle *lttng_payload_view_pop_fd_handle(
+               struct lttng_payload_view *view)
 {
-       int ret = 0;
-       size_t fd_count;
+       struct fd_handle *handle = NULL;
+       size_t fd_handle_count;
        size_t *pos;
 
        if (!view) {
-               ret = -1;
                goto end;
        }
 
-       fd_count = lttng_dynamic_array_get_count(&view->_fds);
-       pos = view->_iterator.p_fds_position ? view->_iterator.p_fds_position :
-               &view->_iterator.fds_position;
-
-       if (*pos >= fd_count) {
-               ret = -1;
+       fd_handle_count = lttng_payload_view_get_fd_handle_count(view);
+       if (fd_handle_count == 0) {
                goto end;
        }
 
-       ret = *((int *) lttng_dynamic_array_get_element(
-                       &view->_fds, *pos));
+       pos = view->_iterator.p_fd_handles_position ?
+                       view->_iterator.p_fd_handles_position :
+                       &view->_iterator.fd_handles_position;
+       handle = lttng_dynamic_pointer_array_get_pointer(&view->_fd_handles,
+                       *pos);
        (*pos)++;
+       fd_handle_get(handle);
 end:
-       return ret;
+       return handle;
 }
index 9e385842b208f1183c9842b1578fe1f3206c6858..a07c0be003c7e9638c0ab8af0f1bd0f0cb6e6326 100644 (file)
@@ -12,6 +12,7 @@
 #include <common/dynamic-array.h>
 
 struct lttng_payload;
+struct fd_handle;
 
 /*
  * An lttng_payload_view references a payload and allows code to share
@@ -21,22 +22,23 @@ struct lttng_payload;
  * payload view) is modified.
  *
  * While a payload view does not allow users to modify the underlying bytes
- * of the payload, it can be used to 'pop' file descriptors using an iterator
- * belonging to the top-level payload view.
+ * of the payload, it can be used to 'pop' file descriptor handles using an
+ * iterator belonging to the top-level payload view.
  *
  * Hence, a payload view created from a        payload or a dynamic buffer contains
- * an implicit file descriptor iterator. Any payload view created from another
- * payload view will share the same underlying file descriptor iterator.
+ * an implicit file descriptor handle iterator. Any payload view created from
+ * another payload view will share the same underlying file descriptor handle
+ * iterator.
  *
- * The rationale for this is that a payload is never consumed directly, it
- * must be consumed through a payload view.
+ * The rationale for this is that a payload is never consumed directly, it must
+ * be consumed through a payload view.
  *
  * Typically, a payload view will be used to rebuild a previously serialized
  * object hierarchy. Sharing an underlying iterator allows aggregate objects
  * to provide a restricted view of the payload to their members, which will
- * report the number of bytes consumed and `pop` the file descriptors they
+ * report the number of bytes consumed and `pop` the file descriptor handle they
  * should own. In return, those objects can create an even narrower view for
- * their children, allowing them to also consume file descriptors.
+ * their children, allowing them to also consume file descriptor handles.
  *
  * Note that a payload view never assumes any ownership of the underlying
  * payload.
@@ -44,10 +46,10 @@ struct lttng_payload;
 struct lttng_payload_view {
        struct lttng_buffer_view buffer;
        /* private */
-       const struct lttng_dynamic_array _fds;
+       const struct lttng_dynamic_pointer_array _fd_handles;
        struct {
-               size_t *p_fds_position;
-               size_t fds_position;
+               size_t *p_fd_handles_position;
+               size_t fd_handles_position;
        } _iterator;
 };
 
@@ -130,24 +132,27 @@ struct lttng_payload_view lttng_payload_view_init_from_buffer(
                const char *src, size_t offset, ptrdiff_t len);
 
 /**
- * Get the number of file descriptors left in a payload view.
+ * Get the number of file descriptor handles left in a payload view.
  *
  * @payload    Payload instance
  *
- * Returns the number of file descriptors left on success, -1 on error.
+ * Returns the number of file descriptor handles left on success, -1 on error.
  */
 LTTNG_HIDDEN
-int lttng_payload_view_get_fd_count(struct lttng_payload_view *payload_view);
+int lttng_payload_view_get_fd_handle_count(
+               struct lttng_payload_view *payload_view);
 
 /**
- * Pop an fd from a payload view.
- * No ownership of the file descriptor is assumed by the payload.
+ * Pop an fd handle from a payload view.
+ *
+ * A reference to the returned fd_handle is acquired on behalf of the caller.
  *
  * @payload    Payload instance
  *
- * Returns a file descriptor on success, -1 on error.
+ * Returns an fd_handle on success, -1 on error.
  */
 LTTNG_HIDDEN
-int lttng_payload_view_pop_fd(struct lttng_payload_view *payload_view);
+struct fd_handle *lttng_payload_view_pop_fd_handle(
+               struct lttng_payload_view *payload_view);
 
 #endif /* LTTNG_PAYLOAD_VIEW_H */
index c4faece18fcadb84fe94fd33ccca23ac857ca85a..70b2c7e5acccbd03f6e0b66ce2a8b9cb687d946a 100644 (file)
 #include <common/dynamic-buffer.h>
 #include <common/error.h>
 
+static
+void release_fd_handle_ref(void *ptr)
+{
+       struct fd_handle *fd_handle = ptr;
+
+       fd_handle_put(fd_handle);
+}
+
 LTTNG_HIDDEN
 void lttng_payload_init(struct lttng_payload *payload)
 {
        assert(payload);
        lttng_dynamic_buffer_init(&payload->buffer);
-       lttng_dynamic_array_init(&payload->_fds, sizeof(int), NULL);
+       lttng_dynamic_pointer_array_init(&payload->_fd_handles,
+                       release_fd_handle_ref);
 }
 
 LTTNG_HIDDEN
@@ -28,38 +37,33 @@ int lttng_payload_copy(const struct lttng_payload *src_payload,
        ret = lttng_dynamic_buffer_append_buffer(
                        &dst_payload->buffer, &src_payload->buffer);
        if (ret) {
-               goto error;
+               goto end;
        }
 
-       for (i = 0; i < lttng_dynamic_array_get_count(&src_payload->_fds);
+       for (i = 0; i < lttng_dynamic_pointer_array_get_count(
+                                       &src_payload->_fd_handles);
                        i++) {
-               int dst_fd;
-               const int src_fd = *((int *) lttng_dynamic_array_get_element(
-                                            &src_payload->_fds, i));
-
-               dst_fd = dup(src_fd);
-               if (dst_fd < 0) {
-                       PERROR("Failed to duplicate file descriptor while copying a payload");
-                       ret = dst_fd;
-                       goto error;
+               struct fd_handle *new_fd_handle;
+               const struct fd_handle *src_fd_handle =
+                               lttng_dynamic_pointer_array_get_pointer(
+                                               &src_payload->_fd_handles, i);
+
+               new_fd_handle = fd_handle_copy(src_fd_handle);
+               if (!new_fd_handle) {
+                       PERROR("Failed to copy fd_handle while copying a payload");
+                       ret = -1;
+                       goto end;
                }
 
-               ret = lttng_payload_push_fd(dst_payload, dst_fd);
+               ret = lttng_payload_push_fd_handle(dst_payload, new_fd_handle);
+               fd_handle_put(new_fd_handle);
                if (ret) {
-                       const int close_ret = close(dst_fd);
-
-                       if (close_ret < 0) {
-                               PERROR("Failed to close duplicated file descriptor while copying a payload");
-                       }
-
-                       goto error;
+                       goto end;
                }
        }
 
 end:
        return ret;
-error:
-       goto end;
 }
 
 LTTNG_HIDDEN
@@ -70,11 +74,19 @@ void lttng_payload_reset(struct lttng_payload *payload)
        }
 
        lttng_dynamic_buffer_reset(&payload->buffer);
-       lttng_dynamic_array_reset(&payload->_fds);
+       lttng_dynamic_pointer_array_reset(&payload->_fd_handles);
 }
 
 LTTNG_HIDDEN
-int lttng_payload_push_fd(struct lttng_payload *payload, int fd)
+void lttng_payload_clear(struct lttng_payload *payload)
+{
+       lttng_dynamic_buffer_set_size(&payload->buffer, 0);
+       lttng_dynamic_pointer_array_clear(&payload->_fd_handles);
+}
+
+LTTNG_HIDDEN
+int lttng_payload_push_fd_handle(struct lttng_payload *payload,
+               struct fd_handle *fd_handle)
 {
        int ret;
 
@@ -83,7 +95,13 @@ int lttng_payload_push_fd(struct lttng_payload *payload, int fd)
                goto end;
        }
 
-       ret = lttng_dynamic_array_add_element(&payload->_fds, &fd);
+       ret = lttng_dynamic_pointer_array_add_pointer(
+                       &payload->_fd_handles, fd_handle);
+       if (ret) {
+               goto end;
+       }
+
+       fd_handle_get(fd_handle);
 end:
        return ret;
 }
index 465a097cfbcdac0b0530372b63eedc95b329cef6..a8f66f36b98b6f82181b4209ff213961f16d55ab 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <common/dynamic-buffer.h>
 #include <common/dynamic-array.h>
+#include <common/fd-handle.h>
 
 /*
  * An lttng_payload encompasses the 'data' (bytes) and any passed file
@@ -19,7 +20,7 @@
 struct lttng_payload {
        struct lttng_dynamic_buffer buffer;
        /* private */
-       struct lttng_dynamic_array _fds;
+       struct lttng_dynamic_pointer_array _fd_handles;
 };
 
 /*
@@ -34,20 +35,31 @@ LTTNG_HIDDEN
 int lttng_payload_copy(const struct lttng_payload *src_payload,
                struct lttng_payload *dst_payload);
 
-/* Release any memory used by the payload. */
+/* Release any memory and references held by the payload. */
 LTTNG_HIDDEN
 void lttng_payload_reset(struct lttng_payload *payload);
 
+/*
+ * Empty the contents of a payload, releasing all references held.
+ * This should be used to put a payload in a re-usable state.
+ *
+ * lttng_payload_reset must still be called on an lttng_payload to
+ * free all allocated memory.
+ */
+LTTNG_HIDDEN
+void lttng_payload_clear(struct lttng_payload *payload);
+
 /**
  * Add an fd to the payload.
- * No ownership of the file descriptor is assumed by the payload.
+ * The payload acquires a reference to the fd_handle.
  *
  * @payload    Payload instance
- * @fd         File descriptor to add to the payload
+ * @fd_handle  File descriptor handle to add to the payload
  *
  * Returns 0 on success, -1 on allocation error.
  */
 LTTNG_HIDDEN
-int lttng_payload_push_fd(struct lttng_payload *payload, int fd);
+int lttng_payload_push_fd_handle(struct lttng_payload *payload,
+               struct fd_handle *fd_handle);
 
 #endif /* LTTNG_PAYLOAD_H */
index f50611b5b0eac52ad8ac92502826038eec10afeb..50200242529992ce4b8244d4c4d897a28d35583d 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <common/common.h>
 #include <common/sessiond-comm/sessiond-comm.h>
+#include <common/fd-handle.h>
 
 #include "unix.h"
 
@@ -435,6 +436,73 @@ ssize_t lttcomm_send_fds_unix_sock(int sock, const int *fds, size_t nb_fd)
        return ret;
 }
 
+/*
+ * Send the fd(s) of a payload view over a unix socket.
+ *
+ * Returns the size of data sent, or negative error value.
+ */
+static
+ssize_t _lttcomm_send_payload_view_fds_unix_sock(int sock,
+               struct lttng_payload_view *view,
+               bool blocking)
+{
+       int i;
+       ssize_t ret;
+       struct lttng_dynamic_array raw_fds;
+       const int fd_count = lttng_payload_view_get_fd_handle_count(view);
+
+       lttng_dynamic_array_init(&raw_fds, sizeof(int), NULL);
+
+       /*
+        * Prepare a contiguous array of file descriptors to send them.
+        *
+        * Note that the reference to each fd is released during the iteration;
+        * we're just getting the numerical value of the fds to conform to the
+        * syscall's interface. We rely on the fact that "view" must remain
+        * valid for the duration of the call and that the underlying payload
+        * owns a reference to the fd_handles.
+        */
+       for (i = 0; i < fd_count; i++) {
+               struct fd_handle *handle =
+                               lttng_payload_view_pop_fd_handle(view);
+               const int raw_fd = fd_handle_get_fd(handle);
+               const int add_ret = lttng_dynamic_array_add_element(
+                               &raw_fds, &raw_fd);
+
+               fd_handle_put(handle);
+               if (add_ret) {
+                       ret = -LTTNG_ERR_NOMEM;
+                       goto end;
+               }
+       }
+
+       if (blocking) {
+               ret = lttcomm_send_fds_unix_sock(sock,
+                               (const int *) raw_fds.buffer.data, fd_count);
+       } else {
+               ret = lttcomm_send_fds_unix_sock_non_block(sock,
+                               (const int *) raw_fds.buffer.data, fd_count);
+       }
+
+end:
+       lttng_dynamic_array_reset(&raw_fds);
+       return ret;
+}
+
+LTTNG_HIDDEN
+ssize_t lttcomm_send_payload_view_fds_unix_sock(int sock,
+               struct lttng_payload_view *view)
+{
+       return _lttcomm_send_payload_view_fds_unix_sock(sock, view, true);
+}
+
+LTTNG_HIDDEN
+ssize_t lttcomm_send_payload_view_fds_unix_sock_non_block(int sock,
+               struct lttng_payload_view *view)
+{
+       return _lttcomm_send_payload_view_fds_unix_sock(sock, view, false);
+}
+
 /*
  * Send a message accompanied by fd(s) over a unix socket.
  * Only use for non blocking socket.
@@ -629,6 +697,107 @@ end:
        return ret;
 }
 
+static
+void close_raw_fd(void *ptr)
+{
+       const int raw_fd = *((const int *) ptr);
+
+       if (raw_fd >= 0) {
+               const int ret = close(raw_fd);
+
+               if (ret) {
+                       PERROR("Failed to close file descriptor %d", raw_fd);
+               }
+       }
+}
+
+static
+enum lttng_error_code add_fds_to_payload(struct lttng_dynamic_array *raw_fds,
+               struct lttng_payload *payload)
+{
+       int i;
+       enum lttng_error_code ret_code = LTTNG_OK;
+       const int fd_count = lttng_dynamic_array_get_count(raw_fds);
+
+       for (i = 0; i < fd_count; i++) {
+               int ret;
+               struct fd_handle *handle;
+               int *raw_fd = (int *) lttng_dynamic_array_get_element(
+                       raw_fds, i);
+
+               handle = fd_handle_create(*raw_fd);
+               if (!handle) {
+                       ret_code = LTTNG_ERR_NOMEM;
+                       goto end;
+               }
+
+               /* FD ownership transferred to the handle. */
+               *raw_fd = -1;
+
+               ret = lttng_payload_push_fd_handle(payload, handle);
+               fd_handle_put(handle);
+               if (ret) {
+                       ret_code = LTTNG_ERR_NOMEM;
+                       goto end;
+               }
+       }
+
+end:
+       return ret_code;
+}
+
+static
+ssize_t _lttcomm_recv_payload_fds_unix_sock(int sock, size_t nb_fd,
+               struct lttng_payload *payload, bool blocking)
+{
+       enum lttng_error_code add_ret;
+       ssize_t ret;
+       struct lttng_dynamic_array raw_fds;
+
+       lttng_dynamic_array_init(&raw_fds, sizeof(int), close_raw_fd);
+       ret = lttng_dynamic_array_set_count(&raw_fds, nb_fd);
+       if (ret) {
+               ret = -LTTNG_ERR_NOMEM;
+               goto end;
+       }
+
+       if (blocking) {
+               ret = lttcomm_recv_fds_unix_sock(
+                               sock, (int *) raw_fds.buffer.data, nb_fd);
+       } else {
+               ret = lttcomm_recv_fds_unix_sock_non_block(
+                               sock, (int *) raw_fds.buffer.data, nb_fd);
+       }
+
+       if (ret < 0) {
+               goto end;
+       }
+
+       add_ret = add_fds_to_payload(&raw_fds, payload);
+       if (add_ret != LTTNG_OK) {
+               ret = - (int) add_ret;
+               goto end;
+       }
+
+end:
+       lttng_dynamic_array_reset(&raw_fds);
+       return ret;
+}
+
+LTTNG_HIDDEN
+ssize_t lttcomm_recv_payload_fds_unix_sock(int sock, size_t nb_fd,
+                          struct lttng_payload *payload)
+{
+       return _lttcomm_recv_payload_fds_unix_sock(sock, nb_fd, payload, true);
+}
+
+LTTNG_HIDDEN
+ssize_t lttcomm_recv_payload_fds_unix_sock_non_block(int sock, size_t nb_fd,
+                          struct lttng_payload *payload)
+{
+       return _lttcomm_recv_payload_fds_unix_sock(sock, nb_fd, payload, false);
+}
+
 /*
  * Recv a message accompanied by fd(s) from a non-blocking unix socket.
  * Only use with non-blocking sockets.
index a975543b3cecc4134bff2f6f369aefc496e322e7..4f69e6d48fe75db60512dc085d61c10ce90b20db 100644 (file)
@@ -13,6 +13,8 @@
 
 #include <common/compat/socket.h>
 #include <common/macros.h>
+#include <common/payload.h>
+#include <common/payload-view.h>
 
 LTTNG_HIDDEN
 int lttcomm_create_unix_sock(const char *pathname);
@@ -31,13 +33,26 @@ int lttcomm_close_unix_sock(int sock);
 LTTNG_HIDDEN
 ssize_t lttcomm_send_fds_unix_sock(int sock, const int *fds, size_t nb_fd);
 LTTNG_HIDDEN
+ssize_t lttcomm_send_payload_view_fds_unix_sock(int sock,
+               struct lttng_payload_view *view);
+LTTNG_HIDDEN
 ssize_t lttcomm_send_fds_unix_sock_non_block(
                int sock, const int *fds, size_t nb_fd);
+LTTNG_HIDDEN
+ssize_t lttcomm_send_payload_view_fds_unix_sock_non_block(int sock,
+               struct lttng_payload_view *view);
+
 /* Recv a message accompanied by fd(s) from a unix socket */
 LTTNG_HIDDEN
 ssize_t lttcomm_recv_fds_unix_sock(int sock, int *fds, size_t nb_fd);
 LTTNG_HIDDEN
+ssize_t lttcomm_recv_payload_fds_unix_sock(int sock, size_t nb_fd,
+               struct lttng_payload *payload);
+LTTNG_HIDDEN
 ssize_t lttcomm_recv_fds_unix_sock_non_block(int sock, int *fds, size_t nb_fd);
+LTTNG_HIDDEN
+ssize_t lttcomm_recv_payload_fds_unix_sock_non_block(int sock, size_t nb_fd,
+               struct lttng_payload *payload);
 
 LTTNG_HIDDEN
 ssize_t lttcomm_recv_unix_sock(int sock, void *buf, size_t len);
index 61ba309dfa38e2f863dd277ddb90590057720f2c..5e66f41c146e6cf9615e75ad71ec9951e949643d 100644 (file)
 #include <sys/types.h>
 #include <sys/unistd.h>
 
+static
+int lttng_userspace_probe_location_function_set_binary_fd(
+               struct lttng_userspace_probe_location *location,
+               struct fd_handle *binary_fd);
+
+static
+int lttng_userspace_probe_location_tracepoint_set_binary_fd(
+               struct lttng_userspace_probe_location *location,
+               struct fd_handle *binary_fd);
+
 enum lttng_userspace_probe_location_lookup_method_type
 lttng_userspace_probe_location_lookup_method_get_type(
                const struct lttng_userspace_probe_location_lookup_method *lookup_method)
@@ -95,11 +105,7 @@ void lttng_userspace_probe_location_function_destroy(
 
        free(location_function->function_name);
        free(location_function->binary_path);
-       if (location_function->binary_fd >= 0) {
-               if (close(location_function->binary_fd)) {
-                       PERROR("close");
-               }
-       }
+       fd_handle_put(location_function->binary_fd);
        free(location);
 }
 
@@ -120,11 +126,7 @@ void lttng_userspace_probe_location_tracepoint_destroy(
        free(location_tracepoint->probe_name);
        free(location_tracepoint->provider_name);
        free(location_tracepoint->binary_path);
-       if (location_tracepoint->binary_fd >= 0) {
-               if (close(location_tracepoint->binary_fd)) {
-                       PERROR("close");
-               }
-       }
+       fd_handle_put(location_tracepoint->binary_fd);
        free(location);
 }
 
@@ -225,7 +227,8 @@ static bool lttng_userspace_probe_location_function_is_equal(
                goto end;
        }
 
-       is_equal = fd_is_equal(a->binary_fd, b->binary_fd);
+       is_equal = fd_is_equal(a->binary_fd ? fd_handle_get_fd(a->binary_fd) : -1,
+                       b->binary_fd ? fd_handle_get_fd(b->binary_fd) : -1);
 end:
        return is_equal;
 }
@@ -237,6 +240,7 @@ lttng_userspace_probe_location_function_create_no_check(const char *binary_path,
                bool open_binary)
 {
        int binary_fd = -1;
+       struct fd_handle *binary_fd_handle = NULL;
        char *function_name_copy = NULL, *binary_path_copy = NULL;
        struct lttng_userspace_probe_location *ret = NULL;
        struct lttng_userspace_probe_location_function *location;
@@ -247,7 +251,13 @@ lttng_userspace_probe_location_function_create_no_check(const char *binary_path,
                        PERROR("Error opening the binary");
                        goto error;
                }
-       } else {
+
+               binary_fd_handle = fd_handle_create(binary_fd);
+               if (!binary_fd) {
+                       goto error;
+               }
+
+               /* Ownership transferred to fd_handle. */
                binary_fd = -1;
        }
 
@@ -271,7 +281,8 @@ lttng_userspace_probe_location_function_create_no_check(const char *binary_path,
 
        location->function_name = function_name_copy;
        location->binary_path = binary_path_copy;
-       location->binary_fd = binary_fd;
+       location->binary_fd = binary_fd_handle;
+       binary_fd_handle = NULL;
        location->instrumentation_type =
                        LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_ENTRY;
 
@@ -289,6 +300,7 @@ error:
                        PERROR("Error closing binary fd in error path");
                }
        }
+       fd_handle_put(binary_fd_handle);
 end:
        return ret;
 }
@@ -323,7 +335,8 @@ static bool lttng_userspace_probe_location_tracepoint_is_equal(
                goto end;
        }
 
-       is_equal = fd_is_equal(a->binary_fd, b->binary_fd);
+       is_equal = fd_is_equal(a->binary_fd ? fd_handle_get_fd(a->binary_fd) : -1,
+                       b->binary_fd ? fd_handle_get_fd(b->binary_fd) : -1);
 
 end:
        return is_equal;
@@ -336,6 +349,7 @@ lttng_userspace_probe_location_tracepoint_create_no_check(const char *binary_pat
                bool open_binary)
 {
        int binary_fd = -1;
+       struct fd_handle *binary_fd_handle = NULL;
        char *probe_name_copy = NULL;
        char *provider_name_copy = NULL;
        char *binary_path_copy = NULL;
@@ -348,7 +362,13 @@ lttng_userspace_probe_location_tracepoint_create_no_check(const char *binary_pat
                        PERROR("open");
                        goto error;
                }
-       } else {
+
+               binary_fd_handle = fd_handle_create(binary_fd);
+               if (!binary_fd) {
+                       goto error;
+               }
+
+               /* Ownership transferred to fd_handle. */
                binary_fd = -1;
        }
 
@@ -379,7 +399,8 @@ lttng_userspace_probe_location_tracepoint_create_no_check(const char *binary_pat
        location->probe_name = probe_name_copy;
        location->provider_name = provider_name_copy;
        location->binary_path = binary_path_copy;
-       location->binary_fd = binary_fd;
+       location->binary_fd = binary_fd_handle;
+       binary_fd_handle = NULL;
 
        ret = &location->parent;
        ret->lookup_method = lookup_method;
@@ -396,6 +417,7 @@ error:
                        PERROR("Error closing binary fd in error path");
                }
        }
+       fd_handle_put(binary_fd_handle);
 end:
        return ret;
 }
@@ -519,10 +541,12 @@ lttng_userspace_probe_location_function_copy(
        struct lttng_userspace_probe_location_lookup_method *lookup_method = NULL;
        const char *binary_path = NULL;
        const char *function_name = NULL;
-       int fd, new_fd;
+       struct lttng_userspace_probe_location_function *function_location;
 
        assert(location);
        assert(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
+       function_location = container_of(
+                       location, typeof(*function_location), parent);
 
         /* Get probe location fields */
        binary_path = lttng_userspace_probe_location_function_get_binary_path(location);
@@ -537,19 +561,6 @@ lttng_userspace_probe_location_function_copy(
                goto error;
        }
 
-       /* Duplicate the binary fd */
-       fd = lttng_userspace_probe_location_function_get_binary_fd(location);
-       if (fd == -1) {
-               ERR("Error getting file descriptor to binary");
-               goto error;
-       }
-
-       new_fd = dup(fd);
-       if (new_fd == -1) {
-               PERROR("Error duplicating file descriptor to binary");
-               goto error;
-       }
-
        /*
         * Duplicate probe location method fields
         */
@@ -561,12 +572,12 @@ lttng_userspace_probe_location_function_copy(
                        lttng_userspace_probe_location_lookup_method_function_elf_copy(
                                        location->lookup_method);
                if (!lookup_method) {
-                       goto close_fd;
+                       goto error;
                }
                break;
        default:
                /* Invalid probe location lookup method. */
-               goto close_fd;
+               goto error;
        }
 
        /* Create the probe_location */
@@ -577,7 +588,8 @@ lttng_userspace_probe_location_function_copy(
        }
 
        /* Set the duplicated fd to the new probe_location */
-       if (lttng_userspace_probe_location_function_set_binary_fd(new_location, new_fd) < 0) {
+       if (lttng_userspace_probe_location_function_set_binary_fd(new_location,
+                       function_location->binary_fd) < 0) {
                goto destroy_probe_location;
        }
 
@@ -587,10 +599,6 @@ destroy_probe_location:
        lttng_userspace_probe_location_destroy(new_location);
 destroy_lookup_method:
        lttng_userspace_probe_location_lookup_method_destroy(lookup_method);
-close_fd:
-       if (close(new_fd) < 0) {
-               PERROR("Error closing duplicated file descriptor in error path");
-       }
 error:
        new_location = NULL;
 end:
@@ -607,12 +615,14 @@ lttng_userspace_probe_location_tracepoint_copy(
        const char *binary_path = NULL;
        const char *probe_name = NULL;
        const char *provider_name = NULL;
-       int fd, new_fd;
+       struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
 
        assert(location);
        assert(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
+       tracepoint_location = container_of(
+                       location, typeof(*tracepoint_location), parent);
 
-        /* Get probe location fields */
+       /* Get probe location fields */
        binary_path = lttng_userspace_probe_location_tracepoint_get_binary_path(location);
        if (!binary_path) {
                ERR("Userspace probe binary path is NULL");
@@ -631,19 +641,6 @@ lttng_userspace_probe_location_tracepoint_copy(
                goto error;
        }
 
-       /* Duplicate the binary fd */
-       fd = lttng_userspace_probe_location_tracepoint_get_binary_fd(location);
-       if (fd == -1) {
-               ERR("Error getting file descriptor to binary");
-               goto error;
-       }
-
-       new_fd = dup(fd);
-       if (new_fd == -1) {
-               PERROR("Error duplicating file descriptor to binary");
-               goto error;
-       }
-
        /*
         * Duplicate probe location method fields
         */
@@ -655,12 +652,12 @@ lttng_userspace_probe_location_tracepoint_copy(
                        lttng_userspace_probe_location_lookup_method_tracepoint_sdt_copy(
                                        location->lookup_method);
                if (!lookup_method) {
-                       goto close_fd;
+                       goto error;
                }
                break;
        default:
                /* Invalid probe location lookup method. */
-               goto close_fd;
+               goto error;
        }
 
        /* Create the probe_location */
@@ -671,7 +668,8 @@ lttng_userspace_probe_location_tracepoint_copy(
        }
 
        /* Set the duplicated fd to the new probe_location */
-       if (lttng_userspace_probe_location_tracepoint_set_binary_fd(new_location, new_fd) < 0) {
+       if (lttng_userspace_probe_location_tracepoint_set_binary_fd(new_location,
+                       tracepoint_location->binary_fd) < 0) {
                goto destroy_probe_location;
        }
 
@@ -681,10 +679,6 @@ destroy_probe_location:
        lttng_userspace_probe_location_destroy(new_location);
 destroy_lookup_method:
        lttng_userspace_probe_location_lookup_method_destroy(lookup_method);
-close_fd:
-       if (close(new_fd) < 0) {
-               PERROR("Error closing duplicated file descriptor in error path");
-       }
 error:
        new_location = NULL;
 end:
@@ -802,7 +796,8 @@ int lttng_userspace_probe_location_function_get_binary_fd(
 
        function_location = container_of(location,
                struct lttng_userspace_probe_location_function, parent);
-       ret = function_location->binary_fd;
+       ret = function_location->binary_fd ?
+                       fd_handle_get_fd(function_location->binary_fd) : -1;
 end:
        return ret;
 }
@@ -867,7 +862,8 @@ int lttng_userspace_probe_location_tracepoint_get_binary_fd(
 
        tracepoint_location = container_of(location,
                struct lttng_userspace_probe_location_tracepoint, parent);
-       ret = tracepoint_location->binary_fd;
+       ret = tracepoint_location->binary_fd ?
+                       fd_handle_get_fd(tracepoint_location->binary_fd) : -1;
 end:
        return ret;
 }
@@ -1015,7 +1011,7 @@ int lttng_userspace_probe_location_function_serialize(
                        ret = -LTTNG_ERR_INVALID;
                        goto end;
                }
-               ret = lttng_payload_push_fd(
+               ret = lttng_payload_push_fd_handle(
                                payload, location_function->binary_fd);
                if (ret) {
                        ret = -LTTNG_ERR_INVALID;
@@ -1109,7 +1105,7 @@ int lttng_userspace_probe_location_tracepoint_serialize(
                        ret = -LTTNG_ERR_INVALID;
                        goto end;
                }
-               ret = lttng_payload_push_fd(
+               ret = lttng_payload_push_fd_handle(
                                payload, location_tracepoint->binary_fd);
                if (ret) {
                        ret = -LTTNG_ERR_INVALID;
@@ -1191,15 +1187,10 @@ int lttng_userspace_probe_location_function_create_from_payload(
        char *function_name = NULL, *binary_path = NULL;
        int ret = 0;
        size_t expected_size;
-       const int binary_fd = lttng_payload_view_pop_fd(view);
+       struct fd_handle *binary_fd = lttng_payload_view_pop_fd_handle(view);
 
        assert(location);
 
-       if (binary_fd < 0) {
-               ret = -LTTNG_ERR_INVALID;
-               goto end;
-       }
-
        if (view->buffer.size < sizeof(*location_function_comm)) {
                ret = -LTTNG_ERR_INVALID;
                goto end;
@@ -1254,17 +1245,13 @@ int lttng_userspace_probe_location_function_create_from_payload(
        ret = lttng_userspace_probe_location_function_set_binary_fd(
                        *location, binary_fd);
        if (ret) {
-               const int close_ret = close(binary_fd);
-
-               if (close_ret) {
-                       PERROR("Failed to close userspace probe function binary fd");
-               }
                ret = -LTTNG_ERR_INVALID;
                goto end;
        }
 
        ret = (int) expected_size;
 end:
+       fd_handle_put(binary_fd);
        free(function_name);
        free(binary_path);
        return ret;
@@ -1280,7 +1267,7 @@ int lttng_userspace_probe_location_tracepoint_create_from_payload(
        char *probe_name = NULL, *provider_name = NULL, *binary_path = NULL;
        int ret = 0;
        size_t expected_size;
-       const int binary_fd = lttng_payload_view_pop_fd(view);
+       struct fd_handle *binary_fd = lttng_payload_view_pop_fd_handle(view);
 
        assert(location);
 
@@ -1355,17 +1342,13 @@ int lttng_userspace_probe_location_tracepoint_create_from_payload(
        ret = lttng_userspace_probe_location_tracepoint_set_binary_fd(
                        *location, binary_fd);
        if (ret) {
-               const int close_ret = close(binary_fd);
-
-               if (close_ret) {
-                       PERROR("Failed to close userspace probe tracepoint binary fd");
-               }
                ret = -LTTNG_ERR_INVALID;
                goto end;
        }
 
        ret = (int) expected_size;
 end:
+       fd_handle_put(binary_fd);
        free(probe_name);
        free(provider_name);
        free(binary_path);
@@ -1505,9 +1488,10 @@ end:
        return ret;
 }
 
-LTTNG_HIDDEN
+static
 int lttng_userspace_probe_location_function_set_binary_fd(
-               struct lttng_userspace_probe_location *location, int binary_fd)
+               struct lttng_userspace_probe_location *location,
+               struct fd_handle *binary_fd)    
 {
        int ret = 0;
        struct lttng_userspace_probe_location_function *function_location;
@@ -1517,23 +1501,16 @@ int lttng_userspace_probe_location_function_set_binary_fd(
 
        function_location = container_of(location,
                        struct lttng_userspace_probe_location_function, parent);
-       if (function_location->binary_fd >= 0) {
-               ret = close(function_location->binary_fd);
-               if (ret) {
-                       PERROR("close");
-                       ret = -LTTNG_ERR_INVALID;
-                       goto end;
-               }
-       }
-
+       fd_handle_put(function_location->binary_fd);
+       fd_handle_get(binary_fd);
        function_location->binary_fd = binary_fd;
-end:
        return ret;
 }
 
-LTTNG_HIDDEN
+static
 int lttng_userspace_probe_location_tracepoint_set_binary_fd(
-               struct lttng_userspace_probe_location *location, int binary_fd)
+               struct lttng_userspace_probe_location *location,
+               struct fd_handle *binary_fd)
 {
        int ret = 0;
        struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
@@ -1543,17 +1520,9 @@ int lttng_userspace_probe_location_tracepoint_set_binary_fd(
 
        tracepoint_location = container_of(location,
                        struct lttng_userspace_probe_location_tracepoint, parent);
-       if (tracepoint_location->binary_fd >= 0) {
-               ret = close(tracepoint_location->binary_fd);
-               if (ret) {
-                       PERROR("close");
-                       ret = -LTTNG_ERR_INVALID;
-                       goto end;
-               }
-       }
-
+       fd_handle_put(tracepoint_location->binary_fd);
+       fd_handle_get(binary_fd);
        tracepoint_location->binary_fd = binary_fd;
-end:
        return ret;
 }
 
@@ -1637,7 +1606,7 @@ int lttng_userspace_probe_location_function_flatten(
 
        flat_probe.function_name = flat_probe_start + sizeof(flat_probe);
        flat_probe.binary_path = flat_probe.function_name + function_name_len;
-       flat_probe.binary_fd = -1;
+       flat_probe.binary_fd = NULL;
        ret = lttng_dynamic_buffer_append(buffer, &flat_probe,
                        sizeof(flat_probe));
        if (ret) {
@@ -1772,7 +1741,7 @@ int lttng_userspace_probe_location_tracepoint_flatten(
        flat_probe.probe_name = flat_probe_start + sizeof(flat_probe);
        flat_probe.provider_name = flat_probe.probe_name + probe_name_len;
        flat_probe.binary_path = flat_probe.provider_name + provider_name_len;
-       flat_probe.binary_fd = -1;
+       flat_probe.binary_fd = NULL;
        ret = lttng_dynamic_buffer_append(buffer, &flat_probe, sizeof(flat_probe));
        if (ret) {
                goto end;
index b2f25ecd06ac58c471f94c4ea34daa2d30383cbb..700a83a13eaa022476935a7bd74c6637943d286e 100644 (file)
 #include <common/compat/string.h>
 #include <common/defaults.h>
 #include <common/dynamic-buffer.h>
+#include <common/dynamic-array.h>
 #include <common/payload.h>
 #include <common/payload-view.h>
 #include <common/sessiond-comm/sessiond-comm.h>
 #include <common/tracker.h>
+#include <common/unix.h>
 #include <common/uri.h>
 #include <common/utils.h>
 #include <lttng/channel-internal.h>
@@ -39,6 +41,7 @@
 #include <lttng/session-internal.h>
 #include <lttng/trigger/trigger-internal.h>
 #include <lttng/userspace-probe-internal.h>
+#include <lttng/lttng-error.h>
 
 #include "filter/filter-ast.h"
 #include "filter/filter-parser.h"
@@ -627,9 +630,10 @@ int lttng_ctl_ask_sessiond_payload(struct lttng_payload_view *message,
 {
        int ret;
        struct lttcomm_lttng_msg llm;
+       const int fd_count = lttng_payload_view_get_fd_handle_count(message);
 
        assert(reply->buffer.size == 0);
-       assert(reply->_fds.size == 0);
+       assert(lttng_dynamic_pointer_array_get_count(&reply->_fd_handles) == 0);
 
        ret = connect_sessiond();
        if (ret < 0) {
@@ -648,10 +652,13 @@ int lttng_ctl_ask_sessiond_payload(struct lttng_payload_view *message,
                goto end;
        }
 
-       if (lttng_payload_view_get_fd_count(message) > 0) {
-               ret = lttcomm_send_fds_unix_sock(sessiond_socket,
-                               (const int *) message->_fds.buffer.data,
-                               lttng_dynamic_array_get_count(&message->_fds));
+       if (fd_count > 0) {
+               ret = lttcomm_send_payload_view_fds_unix_sock(sessiond_socket,
+                               message);
+               if (ret < 0) {
+                       ret = -LTTNG_ERR_FATAL;
+                       goto end;
+               }
        }
 
        /* Get header from data transmission */
@@ -685,19 +692,9 @@ int lttng_ctl_ask_sessiond_payload(struct lttng_payload_view *message,
        }
 
        if (llm.fd_count > 0) {
-               ret = lttng_dynamic_array_set_count(&reply->_fds, llm.fd_count);
-               if (ret) {
-                       ret = -LTTNG_ERR_NOMEM;
-                       goto end;
-               }
-
-               ret = lttcomm_recv_fds_unix_sock(sessiond_socket,
-                               (int *) reply->_fds.buffer.data, llm.fd_count);
-               if (ret > 0 && ret != llm.fd_count * sizeof(int)) {
-                       ret = -LTTNG_ERR_INVALID_PROTOCOL;
-                       goto end;
-               } else if (ret <= 0) {
-                       ret = -LTTNG_ERR_FATAL;
+               ret = lttcomm_recv_payload_fds_unix_sock(
+                               sessiond_socket, llm.fd_count, reply);
+               if (ret < 0) {
                        goto end;
                }
        }
@@ -1360,7 +1357,7 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle,
        {
                struct lttng_payload_view view = lttng_payload_view_from_payload(
                        &payload, 0, -1);
-               int fd_count = lttng_payload_view_get_fd_count(&view);
+               int fd_count = lttng_payload_view_get_fd_handle_count(&view);
                int fd_to_send;
 
                if (fd_count < 0) {
@@ -1369,12 +1366,15 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle,
 
                assert(fd_count == 0 || fd_count == 1);
                if (fd_count == 1) {
-                       ret = lttng_payload_view_pop_fd(&view);
-                       if (ret < 0) {
+                       struct fd_handle *handle =
+                                       lttng_payload_view_pop_fd_handle(&view);
+
+                       if (!handle) {
                                goto mem_error;
                        }
 
-                       fd_to_send = ret;
+                       fd_to_send = fd_handle_get_fd(handle);
+                       fd_handle_put(handle);
                }
 
                ret = lttng_ctl_ask_sessiond_fds_varlen(&lsm,
index 11c57f21de911e842f53a95c0342558fe2a81f15..be97d49904481f6ae01819dec5ffe98993b8d760 100644 (file)
@@ -8,6 +8,7 @@
 #include <common/payload.h>
 #include <common/payload-view.h>
 #include <tap/tap.h>
+#include <sys/eventfd.h>
 
 static const int TEST_COUNT = 5;
 
@@ -20,16 +21,28 @@ static void test_fd_push_pop_order(void)
 {
        int ret, i;
        struct lttng_payload payload;
+       int fds[3];
 
        lttng_payload_init(&payload);
 
        diag("Validating fd push/pop order");
        for (i = 0; i < 3; i++) {
-               ret = lttng_payload_push_fd(&payload, i);
+               int fd = eventfd(0, 0);
+               struct fd_handle *handle;
+
+               assert(fd >= 0);
+               fds[i] = fd;
+
+               handle = fd_handle_create(fd);
+               assert(handle);
+
+               ret = lttng_payload_push_fd_handle(&payload, handle);
+               fd_handle_put(handle);
                if (ret) {
                        break;
                }
        }
+
        ok(ret == 0, "Added three file descriptors to an lttng_payload");
 
        {
@@ -39,8 +52,11 @@ static void test_fd_push_pop_order(void)
                                        &payload, 0, -1);
 
                for (i = 0; i < 3; i++) {
-                       ret = lttng_payload_view_pop_fd(&view);
-                       fail_pop |= ret != i;
+                       struct fd_handle *handle =
+                                       lttng_payload_view_pop_fd_handle(&view);
+
+                       fail_pop |= fd_handle_get_fd(handle) != fds[i];
+                       fd_handle_put(handle);
                }
 
                ok(!fail_pop, "File descriptors are popped from a payload view in the order of insertion");
@@ -59,26 +75,38 @@ static void test_fd_push_pop_imbalance(void)
 
        diag("Validating fd pop imbalance");
        for (i = 0; i < 10; i++) {
-               ret = lttng_payload_push_fd(&payload, i);
+               struct fd_handle *handle;
+               int fd = eventfd(0, 0);
+
+               assert(fd >= 0);
+
+               handle = fd_handle_create(fd);
+               assert(handle);
+
+               ret = lttng_payload_push_fd_handle(&payload, handle);
+               fd_handle_put(handle);
                if (ret) {
                        break;
                }
        }
 
        {
+               struct fd_handle *handle;
                struct lttng_payload_view view =
                                lttng_payload_view_from_payload(
                                        &payload, 0, -1);
 
                for (i = 0; i < 10; i++) {
-                       ret = lttng_payload_view_pop_fd(&view);
-                       if (ret == -1) {
+                       handle = lttng_payload_view_pop_fd_handle(&view);
+                       fd_handle_put(handle);
+                       if (!handle) {
                                goto fail;
                        }
                }
 
-               ret = lttng_payload_view_pop_fd(&view);
-               ok(ret == -1, test_description);
+               handle = lttng_payload_view_pop_fd_handle(&view);
+               ok(!handle, test_description);
+               fd_handle_put(handle);
        }
 
        lttng_payload_reset(&payload);
@@ -91,53 +119,70 @@ fail:
 static void test_fd_pop_fd_root_views(void)
 {
        int ret, i;
-       const int fd = 42;
+       const int fd = eventfd(0, 0);
+       struct fd_handle *handle = fd_handle_create(fd);
        struct lttng_payload payload;
        const char * const test_description = "Same file descriptor returned when popping from different top-level views";
 
        lttng_payload_init(&payload);
+       assert(handle);
 
        diag("Validating root view fd pop behaviour");
-       ret = lttng_payload_push_fd(&payload, fd);
+       ret = lttng_payload_push_fd_handle(&payload, handle);
        if (ret) {
                goto fail;
        }
 
        for (i = 0; i < 5; i++) {
+               int view_fd;
+               struct fd_handle *view_handle;
                struct lttng_payload_view view =
                                lttng_payload_view_from_payload(
                                        &payload, 0, -1);
 
-               ret = lttng_payload_view_pop_fd(&view);
-               if (ret != fd) {
+               view_handle = lttng_payload_view_pop_fd_handle(&view);
+               if (!view_handle) {
+                       goto fail;
+               }
+
+               view_fd = fd_handle_get_fd(view_handle);
+               fd_handle_put(view_handle);
+               if (view_fd != fd || view_handle != handle) {
                        goto fail;
                }
        }
 
        lttng_payload_reset(&payload);
        pass(test_description);
+       fd_handle_put(handle);
        return;
 fail:
        lttng_payload_reset(&payload);
        fail(test_description);
+       fd_handle_put(handle);
 }
 
 static void test_fd_pop_fd_descendant_views(void)
 {
        int ret;
        const int fd1 = 42, fd2 = 1837;
+       struct fd_handle *handle1 = fd_handle_create(fd1);
+       struct fd_handle *handle2 = fd_handle_create(fd2);
+       struct fd_handle *view_handle1 = NULL, *view_handle2 = NULL;
        struct lttng_payload payload;
        const char * const test_description = "Different file descriptors returned when popping from descendant views";
 
        lttng_payload_init(&payload);
+       assert(handle1);
+       assert(handle2);
 
        diag("Validating descendant view fd pop behaviour");
-       ret = lttng_payload_push_fd(&payload, fd1);
+       ret = lttng_payload_push_fd_handle(&payload, handle1);
        if (ret) {
                goto fail;
        }
 
-       ret = lttng_payload_push_fd(&payload, fd2);
+       ret = lttng_payload_push_fd_handle(&payload, handle2);
        if (ret) {
                goto fail;
        }
@@ -150,23 +195,31 @@ static void test_fd_pop_fd_descendant_views(void)
                        lttng_payload_view_from_view(
                                &view1, 0, -1);
 
-               ret = lttng_payload_view_pop_fd(&view1);
-               if (ret != fd1) {
+               view_handle1 = lttng_payload_view_pop_fd_handle(&view1);
+               if (!view_handle1 || fd_handle_get_fd(view_handle1) != fd1) {
                        goto fail;
                }
 
-               ret = lttng_payload_view_pop_fd(&view2);
-               if (ret != fd2) {
+               view_handle2 = lttng_payload_view_pop_fd_handle(&view2);
+               if (!view_handle2 || fd_handle_get_fd(view_handle2) != fd2) {
                        goto fail;
                }
        }
 
        lttng_payload_reset(&payload);
        pass(test_description);
+       fd_handle_put(handle1);
+       fd_handle_put(handle2);
+       fd_handle_put(view_handle1);
+       fd_handle_put(view_handle2);
        return;
 fail:
        lttng_payload_reset(&payload);
        fail(test_description);
+       fd_handle_put(handle1);
+       fd_handle_put(handle2);
+       fd_handle_put(view_handle1);
+       fd_handle_put(view_handle2);
 }
 
 int main(void)
This page took 0.048438 seconds and 4 git commands to generate.