#include <lttng/userspace-probe.h>
#include <common/macros.h>
+#include <common/fd-handle.h>
#include <stdbool.h>
struct lttng_payload;
* 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;
};
* 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
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
/*
* 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);
/*
* 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);
#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"
};
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;
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
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);
}
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;
}
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) {
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:
.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 ...");
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,
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);
}
return (struct lttng_payload_view) {
.buffer = lttng_buffer_view_from_dynamic_buffer(
&payload->buffer, offset, len),
- ._fds = payload->_fds,
+ ._fd_handles = payload->_fd_handles,
};
}
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,
};
}
}
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;
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;
}
#include <common/dynamic-array.h>
struct lttng_payload;
+struct fd_handle;
/*
* An lttng_payload_view references a payload and allows code to share
* 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.
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;
};
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 */
#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
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
}
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;
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;
}
#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
struct lttng_payload {
struct lttng_dynamic_buffer buffer;
/* private */
- struct lttng_dynamic_array _fds;
+ struct lttng_dynamic_pointer_array _fd_handles;
};
/*
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 */
#include <common/common.h>
#include <common/sessiond-comm/sessiond-comm.h>
+#include <common/fd-handle.h>
#include "unix.h"
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.
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.
#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);
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);
#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)
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);
}
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);
}
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;
}
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;
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;
}
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;
PERROR("Error closing binary fd in error path");
}
}
+ fd_handle_put(binary_fd_handle);
end:
return ret;
}
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;
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;
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;
}
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;
PERROR("Error closing binary fd in error path");
}
}
+ fd_handle_put(binary_fd_handle);
end:
return ret;
}
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);
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
*/
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 */
}
/* 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;
}
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:
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");
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
*/
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 */
}
/* 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;
}
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:
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;
}
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;
}
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;
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;
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;
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;
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);
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);
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;
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;
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;
}
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) {
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;
#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>
#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"
{
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) {
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 */
}
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;
}
}
{
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) {
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,
#include <common/payload.h>
#include <common/payload-view.h>
#include <tap/tap.h>
+#include <sys/eventfd.h>
static const int TEST_COUNT = 5;
{
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");
{
&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");
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);
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;
}
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)