From 6684bfa4a76f566ff024d4f2159f59f2e783d8c2 Mon Sep 17 00:00:00 2001 From: Christian Babeux Date: Sun, 2 Dec 2012 20:37:18 -0500 Subject: [PATCH] Cygwin: Pass file paths instead of file descriptors over UNIX sockets Cygwin doesn't support file descriptors passing over UNIX sockets [1]. LTTng-ust and LTTng-tools make extensive use of this feature to pass the shm and the wakeup pipe file descriptor from the userspace tracer to the session daemon. The sessiond then pass those file descriptors to the consumer. To workaround this limitation, we pass the file paths of the shm and the named wakeup pipe. These paths are relayed by the sessiond to the consumer. The consumer then needs to open these paths. The files are created in /tmp/lttng-fds and have the following format: SHM : ust-shm-- Wakeup pipe : ust-wait-- [1] - http://cygwin.com/ml/cygwin/2009-10/msg00403.html Signed-off-by: Christian Babeux --- src/bin/lttng-sessiond/lttng-ust-abi.h | 6 ++ src/bin/lttng-sessiond/ust-consumer.c | 65 ++++++++++++++----- src/common/sessiond-comm/sessiond-comm.c | 83 ++++++++++++++++++++++++ src/common/sessiond-comm/sessiond-comm.h | 4 ++ src/common/ust-consumer/ust-consumer.c | 80 ++++++++++++++++++++--- 5 files changed, 211 insertions(+), 27 deletions(-) diff --git a/src/bin/lttng-sessiond/lttng-ust-abi.h b/src/bin/lttng-sessiond/lttng-ust-abi.h index 1bf82ed44..c54ef2fbf 100644 --- a/src/bin/lttng-sessiond/lttng-ust-abi.h +++ b/src/bin/lttng-sessiond/lttng-ust-abi.h @@ -131,7 +131,9 @@ struct lttng_ust_tracepoint_iter { struct lttng_ust_object_data { int handle; int shm_fd; + char *shm_path; int wait_fd; + char *wait_pipe_path; uint64_t memory_map_size; char padding[LTTNG_UST_OBJECT_DATA_PADDING]; }; @@ -201,12 +203,16 @@ struct lttng_ust_obj; union ust_args { struct { int *shm_fd; + char *shm_path; int *wait_fd; + char *wait_pipe_path; uint64_t *memory_map_size; } channel; struct { int *shm_fd; + char *shm_path; int *wait_fd; + char *wait_pipe_path; uint64_t *memory_map_size; } stream; }; diff --git a/src/bin/lttng-sessiond/ust-consumer.c b/src/bin/lttng-sessiond/ust-consumer.c index 03b0c7d03..9a577b616 100644 --- a/src/bin/lttng-sessiond/ust-consumer.c +++ b/src/bin/lttng-sessiond/ust-consumer.c @@ -36,7 +36,7 @@ static int send_channel_streams(int sock, struct ust_app_channel *uchan, uid_t uid, gid_t gid) { - int ret, fd; + int ret; struct lttcomm_consumer_msg lum; struct ltt_ust_stream *stream, *tmp; @@ -61,15 +61,17 @@ static int send_channel_streams(int sock, PERROR("send consumer channel"); goto error; } - fd = uchan->obj->shm_fd; - ret = lttcomm_send_fds_unix_sock(sock, &fd, 1); + + DBG("Sending channel shm path: %s\n", uchan->obj->shm_path); + ret = lttcomm_send_string(sock, + uchan->obj->shm_path, + strlen(uchan->obj->shm_path)); if (ret < 0) { - PERROR("send consumer channel ancillary data"); + PERROR("send consumer channel shm path"); goto error; } cds_list_for_each_entry_safe(stream, tmp, &uchan->streams.head, list) { - int fds[2]; if (!stream->obj->shm_fd) { continue; @@ -95,11 +97,22 @@ static int send_channel_streams(int sock, goto error; } - fds[0] = stream->obj->shm_fd; - fds[1] = stream->obj->wait_fd; - ret = lttcomm_send_fds_unix_sock(sock, fds, 2); + DBG("Sending stream shm path: %s\n", stream->obj->shm_path); + ret = lttcomm_send_string(sock, + stream->obj->shm_path, + strlen(stream->obj->shm_path)); if (ret < 0) { - PERROR("send consumer stream ancillary data"); + PERROR("send consumer stream shm path"); + goto error; + } + + DBG("Sending stream wait pipe path: %s\n", stream->obj->wait_pipe_path); + ret = lttcomm_send_string(sock, + stream->obj->wait_pipe_path, + strlen(stream->obj->wait_pipe_path)); + + if (ret < 0) { + PERROR("send consumer stream wait pipe path"); goto error; } } @@ -131,9 +144,6 @@ int ust_consumer_send_session(int consumer_fd, struct ust_app_session *usess) } if (usess->metadata->obj->shm_fd != 0) { - int fd; - int fds[2]; - /* Send metadata channel fd */ lum.cmd_type = LTTNG_CONSUMER_ADD_CHANNEL; lum.u.channel.channel_key = usess->metadata->obj->shm_fd; @@ -145,8 +155,11 @@ int ust_consumer_send_session(int consumer_fd, struct ust_app_session *usess) PERROR("send consumer channel"); goto error; } - fd = usess->metadata->obj->shm_fd; - ret = lttcomm_send_fds_unix_sock(sock, &fd, 1); + + DBG("Sending metadata channel shm path: %s\n", usess->metadata->obj->shm_path); + ret = lttcomm_send_string(sock, + usess->metadata->obj->shm_path, + strlen(usess->metadata->obj->shm_path)); if (ret < 0) { PERROR("send consumer metadata channel"); goto error; @@ -169,13 +182,29 @@ int ust_consumer_send_session(int consumer_fd, struct ust_app_session *usess) PERROR("send consumer metadata stream"); goto error; } - fds[0] = usess->metadata->stream_obj->shm_fd; - fds[1] = usess->metadata->stream_obj->wait_fd; - ret = lttcomm_send_fds_unix_sock(sock, fds, 2); + + DBG("Sending metadata stream shm path: %s\n", + usess->metadata->stream_obj->shm_path); + ret = lttcomm_send_string(sock, + usess->metadata->stream_obj->shm_path, + strlen(usess->metadata->stream_obj->shm_path)); + if (ret < 0) { - PERROR("send consumer stream"); + PERROR("send consumer shm stream"); + goto error; + } + + DBG("Sending metadata stream wait pipe path: %s\n", + usess->metadata->stream_obj->wait_pipe_path); + ret = lttcomm_send_string(sock, + usess->metadata->stream_obj->wait_pipe_path, + strlen(usess->metadata->stream_obj->wait_pipe_path)); + + if (ret < 0) { + PERROR("send consumer shm stream"); goto error; } + } /* Send each channel fd streams of session */ diff --git a/src/common/sessiond-comm/sessiond-comm.c b/src/common/sessiond-comm/sessiond-comm.c index b762694e5..3286d3eac 100644 --- a/src/common/sessiond-comm/sessiond-comm.c +++ b/src/common/sessiond-comm/sessiond-comm.c @@ -455,6 +455,89 @@ end: return ret; } +ssize_t lttcomm_send_string(int sock, char *str, size_t len) +{ + ssize_t slen, ret = -1; + + if (!str) { + goto end; + } + + /* Send string len first */ + slen = lttcomm_send_unix_sock(sock, &len, sizeof(len)); + + if (slen != sizeof(len)) { + fprintf(stderr, + "Unexpected sent size. Expected %zu got %zu\n", + sizeof(len), slen); + ret = -1; + goto end; + } + + /* Send the actual string */ + slen = lttcomm_send_unix_sock(sock, str, len); + if (slen != len) { + fprintf(stderr, + "Unexpected sent size. Expected %zu got %zu\n", + len, slen); + ret = -1; + goto end; + } + + ret = slen; + +end: + return ret; +} + +/* + * Allocate and return the received string. + * Return NULL on error. + * Caller is responsible of freeing the allocated string. + */ +char *lttcomm_recv_string(int sock) +{ + ssize_t rlen; + size_t len; + char *ret; + + /* Get the string len first */ + rlen = lttcomm_recv_unix_sock(sock, &len, sizeof(len)); + + if (rlen != sizeof(len)) { + fprintf(stderr, + "Unexpected received size. Expected %zu got %zu\n", + sizeof(len), rlen); + ret = NULL; + goto end; + } + + /* Account for the NULL byte */ + ret = malloc(len + 1); + if (!ret) { + ret = NULL; + goto end; + } + + /* Get the actual string */ + rlen = lttcomm_recv_unix_sock(sock, ret, len); + if (rlen != len) { + fprintf(stderr, + "Unexpected received size. Expected %zu got %zu\n", + len, rlen); + free(ret); + ret = NULL; + goto end; + } + + /* Set terminating NULL byte */ + ret[len] = '\0'; + +end: + return ret; +} + + /* * Send a message with credentials over a unix socket. * diff --git a/src/common/sessiond-comm/sessiond-comm.h b/src/common/sessiond-comm/sessiond-comm.h index d37970797..0de9e8b1b 100644 --- a/src/common/sessiond-comm/sessiond-comm.h +++ b/src/common/sessiond-comm/sessiond-comm.h @@ -299,6 +299,10 @@ extern ssize_t lttcomm_recv_fds_unix_sock(int sock, int *fds, size_t nb_fd); extern ssize_t lttcomm_recv_unix_sock(int sock, void *buf, size_t len); extern ssize_t lttcomm_send_unix_sock(int sock, void *buf, size_t len); +/* Send/recv string over unix socket */ +extern ssize_t lttcomm_send_string(int sock, char *str, size_t len); +extern char *lttcomm_recv_string(int sock); + extern ssize_t lttcomm_send_creds_unix_sock(int sock, void *buf, size_t len); extern ssize_t lttcomm_recv_creds_unix_sock(int sock, void *buf, size_t len, lttng_sock_cred *creds); diff --git a/src/common/ust-consumer/ust-consumer.c b/src/common/ust-consumer/ust-consumer.c index 935f6f311..97b890bf2 100644 --- a/src/common/ust-consumer/ust-consumer.c +++ b/src/common/ust-consumer/ust-consumer.c @@ -167,18 +167,38 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx, { struct lttng_consumer_channel *new_channel; int fds[1]; - size_t nb_fd = 1; + char *path; /* block */ if (lttng_consumer_poll_socket(consumer_sockpoll) < 0) { return -EINTR; } - ret = lttcomm_recv_fds_unix_sock(sock, fds, nb_fd); - if (ret != sizeof(fds)) { + + path = lttcomm_recv_string(sock); + + if (!path) { lttng_consumer_send_error(ctx, CONSUMERD_ERROR_RECV_FD); - return ret; + return -1; + } + + DBG("consumer_add_channel received path %s", path); + + fds[0] = open(path, O_RDWR); + + if (fds[0] < 0) { + DBG("consumer_add_channel open error on path %s", path); + free(path); + return -1; + } + + if (fcntl(fds[0], F_SETFD, FD_CLOEXEC) < 0) { + DBG("consumer_add_channel fcntl error"); + free(path); + return -1; } + free(path); + DBG("consumer_add_channel %d", msg.u.channel.channel_key); new_channel = consumer_allocate_channel(msg.u.channel.channel_key, @@ -204,17 +224,59 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx, case LTTNG_CONSUMER_ADD_STREAM: { struct lttng_consumer_stream *new_stream; - int fds[2]; - size_t nb_fd = 2; + int fds[2], i; + char *shm_path, *wait_pipe_path; /* block */ if (lttng_consumer_poll_socket(consumer_sockpoll) < 0) { return -EINTR; } - ret = lttcomm_recv_fds_unix_sock(sock, fds, nb_fd); - if (ret != sizeof(fds)) { + + shm_path = lttcomm_recv_string(sock); + + if (!shm_path) { lttng_consumer_send_error(ctx, CONSUMERD_ERROR_RECV_FD); - return ret; + return -1; + } + + wait_pipe_path = lttcomm_recv_string(sock); + + if (!wait_pipe_path) { + lttng_consumer_send_error(ctx, CONSUMERD_ERROR_RECV_FD); + free(shm_path); + return -1; + } + + DBG("consumer_add_stream received path %s", shm_path); + DBG("consumer_add_stream received path %s", wait_pipe_path); + + fds[0] = open(shm_path, O_RDWR); + + if (fds[0] < 0) { + DBG("consumer_add_stream open error on path %s", shm_path); + free(shm_path); + free(wait_pipe_path); + return -1; + } + + fds[1] = open(wait_pipe_path, O_RDONLY); + + if (fds[1] < 0) { + DBG("consumer_add_stream open error on path %s", wait_pipe_path); + PERROR("open"); + free(shm_path); + free(wait_pipe_path); + return -1; + } + + free(shm_path); + free(wait_pipe_path); + + for (i = 0; i < 2; ++i) { + if (fcntl(fds[i], F_SETFD, FD_CLOEXEC) < 0) { + DBG("consumer_add_stream fcntl error"); + return -1; + } } DBG("consumer_add_stream %s (%d,%d)", msg.u.stream.path_name, -- 2.34.1