Cygwin: Pass file paths instead of file descriptors over UNIX sockets
authorChristian Babeux <christian.babeux@efficios.com>
Mon, 3 Dec 2012 01:37:18 +0000 (20:37 -0500)
committerChristian Babeux <christian.babeux@efficios.com>
Fri, 7 Dec 2012 20:17:55 +0000 (15:17 -0500)
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-<pid>-<uuid>
Wakeup pipe : ust-wait-<pid>-<uuid>

[1] - http://cygwin.com/ml/cygwin/2009-10/msg00403.html

Signed-off-by: Christian Babeux <christian.babeux@efficios.com>
src/bin/lttng-sessiond/lttng-ust-abi.h
src/bin/lttng-sessiond/ust-consumer.c
src/common/sessiond-comm/sessiond-comm.c
src/common/sessiond-comm/sessiond-comm.h
src/common/ust-consumer/ust-consumer.c

index 1bf82ed4431ee8cc1267f8e6606012f05f7bad43..c54ef2fbf7040f4663caedc9870ea116c541a894 100644 (file)
@@ -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;
 };
index 03b0c7d03ecee91f63dff4317dc956c10130f7fc..9a577b61671aa8c04e2aec286ce56e0e20d0c7f8 100644 (file)
@@ -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 */
index b762694e530ce3e665dc7a1910ef5371f8b43148..3286d3eac2353ce1eca276ef9df679b5d903c776 100644 (file)
@@ -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.
  *
index d37970797445274ff5368b7a5f7c2cb709f7feec..0de9e8b1b0925dd08b5003bdc409ebd6478127b4 100644 (file)
@@ -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);
index 935f6f31139e4e095219e1bb2e9c59d420718572..97b890bf25340ba885f65a5c394d74de187126dd 100644 (file)
@@ -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,
This page took 0.030867 seconds and 4 git commands to generate.