Cygwin: Pass file paths instead of file descriptors over UNIX sockets
authorChristian Babeux <christian.babeux@efficios.com>
Wed, 28 Nov 2012 21:28:22 +0000 (16:28 -0500)
committerChristian Babeux <christian.babeux@efficios.com>
Wed, 28 Nov 2012 21:35:20 +0000 (16:35 -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>

The libringbuffer has been modified to automatically create these files
on shm creation. Take note that the shm path is actually a symlink
to the shm in /dev/shm. Also, this change introduce an additional dependency
to libuuid in libringbuffer.

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

18 files changed:
include/lttng/ust-abi.h
include/lttng/ust-events.h
include/ust-comm.h
liblttng-ust-comm/lttng-ust-comm.c
liblttng-ust-ctl/ustctl.c
liblttng-ust/ltt-events.c
liblttng-ust/ltt-ring-buffer-client.h
liblttng-ust/ltt-ring-buffer-metadata-client.h
liblttng-ust/lttng-ust-abi.c
liblttng-ust/lttng-ust-comm.c
libringbuffer/Makefile.am
libringbuffer/frontend.h
libringbuffer/ring_buffer_frontend.c
libringbuffer/shm.c
libringbuffer/shm.h
libringbuffer/shm_types.h
tests/ust-basic-tracing/ust-basic-tracing.c
tests/ust-multi-test/ust-multi-test.c

index b3af9bf49528d6e131d44c10ff86db59699e316f..86edba90f8134bbc2cb28941fda01f51246b4e99 100644 (file)
@@ -128,7 +128,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];
 };
@@ -198,12 +200,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 8a40aadfd24940e3c9998ceaaab093363a7f8d47..b892fbf84f7190e273ad866fcd54b30870d70ac0 100644 (file)
@@ -303,13 +303,15 @@ struct ltt_channel_ops {
                                size_t subbuf_size, size_t num_subbuf,
                                unsigned int switch_timer_interval,
                                unsigned int read_timer_interval,
-                               int **shm_fd, int **wait_fd,
+                               int **shm_fd, char **shm_path,
+                                int **wait_fd, char **wait_pipe_path,
                                uint64_t **memory_map_size,
                                struct ltt_channel *chan_priv_init);
        void (*channel_destroy)(struct ltt_channel *ltt_chan);
        struct lttng_ust_lib_ring_buffer *(*buffer_read_open)(struct channel *chan,
                                struct lttng_ust_shm_handle *handle,
-                               int **shm_fd, int **wait_fd,
+                                int **shm_fd, char **shm_path,
+                               int **wait_fd, char **wait_pipe_path,
                                uint64_t **memory_map_size);
        void (*buffer_read_close)(struct lttng_ust_lib_ring_buffer *buf,
                                struct lttng_ust_shm_handle *handle);
@@ -390,7 +392,8 @@ struct ltt_channel *ltt_channel_create(struct ltt_session *session,
                                       size_t subbuf_size, size_t num_subbuf,
                                       unsigned int switch_timer_interval,
                                       unsigned int read_timer_interval,
-                                      int **shm_fd, int **wait_fd,
+                                      int **shm_fd, char **shm_path,
+                                      int **wait_fd, char **wait_pipe_path,
                                       uint64_t **memory_map_size,
                                       struct ltt_channel *chan_priv_init);
 struct ltt_channel *ltt_global_channel_create(struct ltt_session *session,
@@ -398,7 +401,8 @@ struct ltt_channel *ltt_global_channel_create(struct ltt_session *session,
                                       size_t subbuf_size, size_t num_subbuf,
                                       unsigned int switch_timer_interval,
                                       unsigned int read_timer_interval,
-                                      int **shm_fd, int **wait_fd,
+                                      int **shm_fd, char **shm_path,
+                                      int **wait_fd, char **wait_pipe_path,
                                       uint64_t **memory_map_size);
 
 int ltt_event_create(struct ltt_channel *chan,
index 7d0b6296524c0f7d6a11566aa5de9f49312a8180..0b80a0ce2d522c9381a716ee60b4253d67aee41e 100644 (file)
@@ -174,4 +174,8 @@ extern int ustcomm_send_app_cmd(int sock,
                struct ustcomm_ust_reply *lur);
 int ustcomm_recv_fd(int sock);
 
+/* Send/recv string over unix socket */
+extern ssize_t ustcomm_send_string(int sock, char *str, size_t len);
+extern char *ustcomm_recv_string(int sock);
+
 #endif /* _LTTNG_UST_COMM_H */
index 078b56a01bb68c49c2322fc2a8f454d597305314..3138016569e8d0c11d2036e2c2fb97225efc399a 100644 (file)
@@ -509,3 +509,85 @@ int ustcomm_recv_fd(int sock)
 end:
        return ret;
 }
+
+ssize_t ustcomm_send_string(int sock, char *str, size_t len)
+{
+       ssize_t slen, ret = -1;
+
+       if (!str) {
+               goto end;
+       }
+
+       /* Send string len first */
+       slen = ustcomm_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 = ustcomm_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 *ustcomm_recv_string(int sock)
+{
+       ssize_t rlen;
+       size_t len;
+       char *ret;
+
+       /* Get the string len first */
+       rlen = ustcomm_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 = ustcomm_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;
+}
index cf7cf87a60d56f00d39bff9a0f8c6ceeb8eba629..39997a2be97dd886bcd63028acb0ccbb2df5facc 100644 (file)
@@ -36,7 +36,9 @@ void init_object(struct lttng_ust_object_data *data)
 {
        data->handle = -1;
        data->shm_fd = -1;
+       data->shm_path = NULL;
        data->wait_fd = -1;
+       data->wait_pipe_path = NULL;
        data->memory_map_size = 0;
 }
 
@@ -74,12 +76,22 @@ int ustctl_release_object(int sock, struct lttng_ust_object_data *data)
                        return ret;
                }
        }
+
+       if (data->shm_path) {
+               free(data->shm_path);
+       }
+
        if (data->wait_fd >= 0) {
                ret = close(data->wait_fd);
                if (ret < 0) {
                        return ret;
                }
        }
+
+       if (data->wait_pipe_path) {
+               free(data->wait_pipe_path);
+       }
+
        return ustctl_release_handle(sock, data->handle);
 }
 
@@ -139,6 +151,7 @@ int ustctl_open_metadata(int sock, int session_handle,
        struct ustcomm_ust_reply lur;
        struct lttng_ust_object_data *metadata_data;
        int ret, err = 0;
+       char *shm_path, *wait_pipe_path;
 
        if (!chops || !_metadata_data)
                return -EINVAL;
@@ -169,22 +182,33 @@ int ustctl_open_metadata(int sock, int session_handle,
        metadata_data->handle = lur.ret_val;
        DBG("received metadata handle %u", metadata_data->handle);
        metadata_data->memory_map_size = lur.u.channel.memory_map_size;
-       /* get shm fd */
-       ret = ustcomm_recv_fd(sock);
-       if (ret < 0)
+       /* get shm path */
+       shm_path = ustcomm_recv_string(sock);
+       if (!shm_path) {
                err = 1;
-       else
-               metadata_data->shm_fd = ret;
+       } else {
+               DBG("Received shm path: %s\n", shm_path);
+               metadata_data->shm_fd = -1;
+               metadata_data->shm_path = shm_path;
+       }
+
        /*
         * We need to get the second FD even if the first fails, because
         * libust expects us to read the two FDs.
         */
-       /* get wait fd */
-       ret = ustcomm_recv_fd(sock);
-       if (ret < 0)
+
+       /* get wait pipe path */
+       wait_pipe_path = ustcomm_recv_string(sock);
+       if (!wait_pipe_path) {
+               free(shm_path);
                err = 1;
-       else
-               metadata_data->wait_fd = ret;
+       } else {
+               DBG("Received wait pipe path: %s\n", wait_pipe_path);
+               metadata_data->wait_fd = -1;
+               metadata_data->wait_pipe_path = wait_pipe_path;
+       }
+
+
        if (err)
                goto error;
        *_metadata_data = metadata_data;
@@ -204,6 +228,7 @@ int ustctl_create_channel(int sock, int session_handle,
        struct ustcomm_ust_reply lur;
        struct lttng_ust_object_data *channel_data;
        int ret, err = 0;
+       char *shm_path, *wait_pipe_path;
 
        if (!chops || !_channel_data)
                return -EINVAL;
@@ -234,22 +259,31 @@ int ustctl_create_channel(int sock, int session_handle,
        channel_data->handle = lur.ret_val;
        DBG("received channel handle %u", channel_data->handle);
        channel_data->memory_map_size = lur.u.channel.memory_map_size;
-       /* get shm fd */
-       ret = ustcomm_recv_fd(sock);
-       if (ret < 0)
+       /* get shm path */
+       shm_path = ustcomm_recv_string(sock);
+       if (!shm_path) {
                err = 1;
-       else
-               channel_data->shm_fd = ret;
+       } else {
+               DBG("Received shm path: %s\n", shm_path);
+               channel_data->shm_fd = -1;
+               channel_data->shm_path = shm_path;
+       }
+
        /*
         * We need to get the second FD even if the first fails, because
         * libust expects us to read the two FDs.
         */
-       /* get wait fd */
-       ret = ustcomm_recv_fd(sock);
-       if (ret < 0)
+       /* get wait pipe path */
+       wait_pipe_path = ustcomm_recv_string(sock);
+       if (!wait_pipe_path) {
+               free(shm_path);
                err = 1;
-       else
-               channel_data->wait_fd = ret;
+       } else {
+               DBG("Received wait pipe path: %s\n", wait_pipe_path);
+               channel_data->wait_fd = -1;
+               channel_data->wait_pipe_path = wait_pipe_path;
+       }
+
        if (err)
                goto error;
        *_channel_data = channel_data;
@@ -272,7 +306,8 @@ int ustctl_create_stream(int sock, struct lttng_ust_object_data *channel_data,
        struct ustcomm_ust_msg lum;
        struct ustcomm_ust_reply lur;
        struct lttng_ust_object_data *stream_data;
-       int ret, fd, err = 0;
+       int ret, err = 0;
+       char *shm_path, *wait_pipe_path;
 
        if (!channel_data || !_stream_data)
                return -EINVAL;
@@ -297,22 +332,31 @@ int ustctl_create_stream(int sock, struct lttng_ust_object_data *channel_data,
        stream_data->handle = lur.ret_val;
        DBG("received stream handle %u", stream_data->handle);
        stream_data->memory_map_size = lur.u.stream.memory_map_size;
-       /* get shm fd */
-       fd = ustcomm_recv_fd(sock);
-       if (fd < 0)
+       /* get shm path */
+       shm_path = ustcomm_recv_string(sock);
+       if (!shm_path) {
                err = 1;
-       else
-               stream_data->shm_fd = fd;
+       } else {
+               DBG("Received shm path: %s\n", shm_path);
+               stream_data->shm_fd = -1;
+               stream_data->shm_path = shm_path;
+       }
+
        /*
         * We need to get the second FD even if the first fails, because
         * libust expects us to read the two FDs.
         */
-       /* get wait fd */
-       fd = ustcomm_recv_fd(sock);
-       if (fd < 0)
+       /* get wait pipe path */
+       wait_pipe_path = ustcomm_recv_string(sock);
+       if (!wait_pipe_path) {
+               free(shm_path);
                err = 1;
-       else
-               stream_data->wait_fd = fd;
+       } else {
+               DBG("Received wait pipe path: %s\n", wait_pipe_path);
+               stream_data->wait_fd = -1;
+               stream_data->wait_pipe_path = wait_pipe_path;
+       }
+
        if (err)
                goto error;
        *_stream_data = stream_data;
@@ -684,6 +728,7 @@ struct lttng_ust_lib_ring_buffer *ustctl_open_stream_read(struct lttng_ust_shm_h
 {
        struct channel *chan;
        int *shm_fd, *wait_fd;
+       char *shm_path, *wait_pipe_path;
        uint64_t *memory_map_size;
        struct lttng_ust_lib_ring_buffer *buf;
        int ret;
@@ -693,7 +738,10 @@ struct lttng_ust_lib_ring_buffer *ustctl_open_stream_read(struct lttng_ust_shm_h
 
        chan = handle->shadow_chan;
        buf = channel_get_ring_buffer(&chan->backend.config,
-               chan, cpu, handle, &shm_fd, &wait_fd, &memory_map_size);
+                                     chan, cpu, handle,
+                                     &shm_fd, &shm_path,
+                                     &wait_fd, &wait_pipe_path,
+                                     &memory_map_size);
        if (!buf)
                return NULL;
        ret = lib_ring_buffer_open_read(buf, handle, 1);
index 2b9037ef48f0d84b8ca237733f5e3438267bb48d..21e8f8ac023979decfd884cb1f92c3f667a09193 100644 (file)
@@ -446,7 +446,8 @@ struct ltt_channel *ltt_channel_create(struct ltt_session *session,
                                       size_t subbuf_size, size_t num_subbuf,
                                       unsigned int switch_timer_interval,
                                       unsigned int read_timer_interval,
-                                      int **shm_fd, int **wait_fd,
+                                      int **shm_fd, char **shm_path,
+                                      int **wait_fd, char **wait_pipe_path,
                                       uint64_t **memory_map_size,
                                       struct ltt_channel *chan_priv_init)
 {
@@ -470,8 +471,9 @@ struct ltt_channel *ltt_channel_create(struct ltt_session *session,
         */
        chan = transport->ops.channel_create(transport_name, buf_addr,
                        subbuf_size, num_subbuf, switch_timer_interval,
-                       read_timer_interval, shm_fd, wait_fd,
-                       memory_map_size, chan_priv_init);
+                       read_timer_interval, shm_fd, shm_path,
+                       wait_fd, wait_pipe_path, memory_map_size,
+                       chan_priv_init);
        if (!chan)
                goto create_error;
        chan->enabled = 1;
index f18b4ed387cdf876dffebd4ae41b7a808b57b55d..b896169e0f64d4257cd46844252e46764b063e4a 100644 (file)
@@ -413,7 +413,8 @@ struct ltt_channel *_channel_create(const char *name,
                                size_t subbuf_size, size_t num_subbuf,
                                unsigned int switch_timer_interval,
                                unsigned int read_timer_interval,
-                               int **shm_fd, int **wait_fd,
+                               int **shm_fd, char **shm_path,
+                               int **wait_fd, char **wait_pipe_path,
                                uint64_t **memory_map_size,
                                struct ltt_channel *chan_priv_init)
 {
@@ -426,7 +427,8 @@ struct ltt_channel *_channel_create(const char *name,
                        chan_priv_init,
                        buf_addr, subbuf_size, num_subbuf,
                        switch_timer_interval, read_timer_interval,
-                       shm_fd, wait_fd, memory_map_size);
+                       shm_fd, shm_path, wait_fd, wait_pipe_path,
+                       memory_map_size);
        if (!handle)
                return NULL;
        ltt_chan = priv;
@@ -443,17 +445,19 @@ void ltt_channel_destroy(struct ltt_channel *ltt_chan)
 
 static
 struct lttng_ust_lib_ring_buffer *ltt_buffer_read_open(struct channel *chan,
-                                            struct lttng_ust_shm_handle *handle,
-                                            int **shm_fd, int **wait_fd,
-                                            uint64_t **memory_map_size)
+                                                      struct lttng_ust_shm_handle *handle,
+                                                      int **shm_fd, char **shm_path,
+                                                      int **wait_fd, char **wait_pipe_path,
+                                                      uint64_t **memory_map_size)
 {
        struct lttng_ust_lib_ring_buffer *buf;
        int cpu;
 
        for_each_channel_cpu(cpu, chan) {
                buf = channel_get_ring_buffer(&client_config, chan,
-                               cpu, handle, shm_fd, wait_fd,
-                               memory_map_size);
+                                             cpu, handle, shm_fd, shm_path,
+                                             wait_fd, wait_pipe_path,
+                                             memory_map_size);
                if (!lib_ring_buffer_open_read(buf, handle, 0))
                        return buf;
        }
@@ -550,11 +554,13 @@ int ltt_flush_buffer(struct channel *chan, struct lttng_ust_shm_handle *handle)
 
        for_each_channel_cpu(cpu, chan) {
                int *shm_fd, *wait_fd;
+               char *shm_path, *wait_pipe_path;
                uint64_t *memory_map_size;
 
                buf = channel_get_ring_buffer(&client_config, chan,
-                               cpu, handle, &shm_fd, &wait_fd,
-                               &memory_map_size);
+                                             cpu, handle, &shm_fd, &shm_path,
+                                             &wait_fd, &wait_pipe_path,
+                                             &memory_map_size);
                lib_ring_buffer_switch(&client_config, buf,
                                SWITCH_ACTIVE, handle);
        }
index acc56fddb890d172b8e2386977df7ce56f501adb..0e9b7fa3f2f3f544158f72b9aed48ca2526d764b 100644 (file)
@@ -183,7 +183,8 @@ struct ltt_channel *_channel_create(const char *name,
                                size_t subbuf_size, size_t num_subbuf,
                                unsigned int switch_timer_interval,
                                unsigned int read_timer_interval,
-                               int **shm_fd, int **wait_fd,
+                               int **shm_fd, char **shm_path,
+                               int **wait_fd, char **wait_pipe_path,
                                uint64_t **memory_map_size,
                                struct ltt_channel *chan_priv_init)
 {
@@ -196,7 +197,8 @@ struct ltt_channel *_channel_create(const char *name,
                        chan_priv_init,
                        buf_addr, subbuf_size, num_subbuf,
                        switch_timer_interval, read_timer_interval,
-                       shm_fd, wait_fd, memory_map_size);
+                       shm_fd, shm_path, wait_fd, wait_pipe_path,
+                       memory_map_size);
        if (!handle)
                return NULL;
        ltt_chan = priv;
@@ -213,14 +215,17 @@ void ltt_channel_destroy(struct ltt_channel *ltt_chan)
 
 static
 struct lttng_ust_lib_ring_buffer *ltt_buffer_read_open(struct channel *chan,
-                                            struct lttng_ust_shm_handle *handle,
-                                            int **shm_fd, int **wait_fd,
-                                            uint64_t **memory_map_size)
+                                                      struct lttng_ust_shm_handle *handle,
+                                                      int **shm_fd, char **shm_path,
+                                                      int **wait_fd, char **wait_pipe_path,
+                                                      uint64_t **memory_map_size)
 {
        struct lttng_ust_lib_ring_buffer *buf;
 
        buf = channel_get_ring_buffer(&client_config, chan,
-                       0, handle, shm_fd, wait_fd, memory_map_size);
+                                     0, handle, shm_fd, shm_path,
+                                     wait_fd, wait_pipe_path,
+                                     memory_map_size);
        if (!lib_ring_buffer_open_read(buf, handle, 0))
                return buf;
        return NULL;
@@ -300,11 +305,13 @@ int ltt_flush_buffer(struct channel *chan, struct lttng_ust_shm_handle *handle)
 {
        struct lttng_ust_lib_ring_buffer *buf;
        int *shm_fd, *wait_fd;
+       char *shm_path, *wait_pipe_path;
        uint64_t *memory_map_size;
 
        buf = channel_get_ring_buffer(&client_config, chan,
-                       0, handle, &shm_fd, &wait_fd,
-                       &memory_map_size);
+                                     0, handle, &shm_fd, &shm_path,
+                                     &wait_fd, &wait_pipe_path,
+                                     &memory_map_size);
        lib_ring_buffer_switch(&client_config, buf,
                        SWITCH_ACTIVE, handle);
        return 0;
index 435763d7e4e6f5f2ffd6754c15be1439f65f41f8..a3edd3ead7d93343c26fd1067449f98713658cb9 100644 (file)
@@ -418,7 +418,9 @@ int lttng_abi_create_channel(int session_objd,
                                  chan_param->switch_timer_interval,
                                  chan_param->read_timer_interval,
                                  &uargs->channel.shm_fd,
+                                 &uargs->channel.shm_path,
                                  &uargs->channel.wait_fd,
+                                 &uargs->channel.wait_pipe_path,
                                  &uargs->channel.memory_map_size,
                                  &chan_priv_init);
        if (!chan) {
@@ -617,9 +619,9 @@ int lttng_abi_open_stream(int channel_objd, struct lttng_ust_stream *info,
        int stream_objd, ret;
 
        buf = channel->ops->buffer_read_open(channel->chan, channel->handle,
-                       &uargs->stream.shm_fd,
-                       &uargs->stream.wait_fd,
-                       &uargs->stream.memory_map_size);
+                    &uargs->stream.shm_fd, &uargs->stream.shm_path,
+                    &uargs->stream.wait_fd, &uargs->stream.wait_pipe_path,
+                    &uargs->stream.memory_map_size);
        if (!buf)
                return -ENOENT;
 
index af7928c3eda10fb0ea13ab01d99f5e01539b436c..3bddf76744216c4d684e940290f0089e67c13c43 100644 (file)
@@ -252,6 +252,7 @@ int handle_message(struct sock_info *sock_info,
        const struct lttng_ust_objd_ops *ops;
        struct ustcomm_ust_reply lur;
        int shm_fd, wait_fd;
+       char *shm_path, *wait_pipe_path;
        union ust_args args;
 
        ust_lock();
@@ -310,14 +311,18 @@ end:
                         * Use lum.u output.
                         */
                        lur.u.stream.memory_map_size = *args.stream.memory_map_size;
-                       shm_fd = *args.stream.shm_fd;
-                       wait_fd = *args.stream.wait_fd;
+                       shm_fd         = *args.stream.shm_fd;
+                       shm_path       = args.stream.shm_path;
+                       wait_fd        = *args.stream.wait_fd;
+                       wait_pipe_path = args.stream.wait_pipe_path;
                        break;
                case LTTNG_UST_METADATA:
                case LTTNG_UST_CHANNEL:
                        lur.u.channel.memory_map_size = *args.channel.memory_map_size;
-                       shm_fd = *args.channel.shm_fd;
-                       wait_fd = *args.channel.wait_fd;
+                       shm_fd         = *args.channel.shm_fd;
+                       shm_path       = args.channel.shm_path;
+                       wait_fd        = *args.channel.wait_fd;
+                       wait_pipe_path = args.channel.wait_pipe_path;
                        break;
                case LTTNG_UST_TRACER_VERSION:
                        lur.u.version = lum->u.version;
@@ -339,23 +344,19 @@ end:
                        && lur.ret_code == USTCOMM_OK) {
                int sendret = 0;
 
-               /* we also need to send the file descriptors. */
-               ret = ustcomm_send_fds_unix_sock(sock,
-                       &shm_fd, &shm_fd,
-                       1, sizeof(int));
+               /* send the shm path */
+               ret = ustcomm_send_string(sock, shm_path, strlen(shm_path));
                if (ret < 0) {
-                       perror("send shm_fd");
+                       perror("send shm_path");
                        sendret = ret;
                }
                /*
                 * The sessiond expects 2 file descriptors, even upon
                 * error.
                 */
-               ret = ustcomm_send_fds_unix_sock(sock,
-                       &wait_fd, &wait_fd,
-                       1, sizeof(int));
+               ret = ustcomm_send_string(sock, wait_pipe_path, strlen(wait_pipe_path));
                if (ret < 0) {
-                       perror("send wait_fd");
+                       perror("send wait_pipe_path");
                        goto error;
                }
                if (sendret) {
index 271c8beed9ffdd385e9a39902d4c463b688d3887..0148a030a6d049bebaf2ee460a26483c760c481c 100644 (file)
@@ -15,6 +15,7 @@ libringbuffer_la_SOURCES = \
 
 libringbuffer_la_LIBADD = \
        -lpthread \
-       -lrt
+       -lrt \
+       -luuid
 
 libringbuffer_la_CFLAGS = -DUST_COMPONENT="libringbuffer" -fno-strict-aliasing
index b1ccddec1e8bfd3367a53f08714f5f153ed4a9b4..784307d00534016c318d785747344a5a922c53f3 100644 (file)
@@ -65,7 +65,8 @@ struct lttng_ust_shm_handle *channel_create(const struct lttng_ust_lib_ring_buff
                                size_t subbuf_size, size_t num_subbuf,
                                unsigned int switch_timer_interval,
                                unsigned int read_timer_interval,
-                               int **shm_fd, int **wait_fd,
+                               int **shm_fd, char **shm_path,
+                               int **wait_fd, char **wait_pipe_path,
                                uint64_t **memory_map_size);
 
 /* channel_handle_create - for consumer. */
@@ -102,7 +103,8 @@ extern struct lttng_ust_lib_ring_buffer *channel_get_ring_buffer(
                                const struct lttng_ust_lib_ring_buffer_config *config,
                                struct channel *chan, int cpu,
                                struct lttng_ust_shm_handle *handle,
-                               int **shm_fd, int **wait_fd,
+                               int **shm_fd, char **shm_path,
+                               int **wait_fd, char **wait_pipe_path,
                                uint64_t **memory_map_size);
 extern int lib_ring_buffer_open_read(struct lttng_ust_lib_ring_buffer *buf,
                                     struct lttng_ust_shm_handle *handle,
index 5913f78d70a899fa78fd2409aded4f10723686b9..c9de2923034231e2edd266b33d45cd554f5f3248 100644 (file)
@@ -439,7 +439,8 @@ struct lttng_ust_shm_handle *channel_create(const struct lttng_ust_lib_ring_buff
                   void *buf_addr, size_t subbuf_size,
                   size_t num_subbuf, unsigned int switch_timer_interval,
                   unsigned int read_timer_interval,
-                  int **shm_fd, int **wait_fd, uint64_t **memory_map_size)
+                  int **shm_fd, char **shm_path,
+                  int **wait_fd, char **wait_pipe_path, uint64_t **memory_map_size)
 {
        int ret, cpu;
        size_t shmsize, chansize;
@@ -530,7 +531,7 @@ struct lttng_ust_shm_handle *channel_create(const struct lttng_ust_lib_ring_buff
                lib_ring_buffer_start_read_timer(buf, handle);
        }
        ref = &handle->chan._ref;
-       shm_get_object_data(handle, ref, shm_fd, wait_fd, memory_map_size);
+       shm_get_object_data(handle, ref, shm_fd, shm_path, wait_fd, wait_pipe_path, memory_map_size);
        return handle;
 
 error_backend_init:
@@ -629,22 +630,23 @@ struct lttng_ust_lib_ring_buffer *channel_get_ring_buffer(
                                        const struct lttng_ust_lib_ring_buffer_config *config,
                                        struct channel *chan, int cpu,
                                        struct lttng_ust_shm_handle *handle,
-                                       int **shm_fd, int **wait_fd,
+                                       int **shm_fd, char **shm_path,
+                                       int **wait_fd, char **wait_pipe_path,
                                        uint64_t **memory_map_size)
 {
        struct shm_ref *ref;
 
        if (config->alloc == RING_BUFFER_ALLOC_GLOBAL) {
                ref = &chan->backend.buf[0].shmp._ref;
-               shm_get_object_data(handle, ref, shm_fd, wait_fd,
-                       memory_map_size);
+               shm_get_object_data(handle, ref, shm_fd, shm_path,
+                                   wait_fd, wait_pipe_path, memory_map_size);
                return shmp(handle, chan->backend.buf[0].shmp);
        } else {
                if (cpu >= num_possible_cpus())
                        return NULL;
                ref = &chan->backend.buf[cpu].shmp._ref;
-               shm_get_object_data(handle, ref, shm_fd, wait_fd,
-                       memory_map_size);
+               shm_get_object_data(handle, ref, shm_fd, shm_path,
+                                   wait_fd, wait_pipe_path, memory_map_size);
                return shmp(handle, chan->backend.buf[cpu].shmp);
        }
 }
index 79977017904308c4f5c05046f176caa7e07fb612..06724e58999aad7169a232bdff91866e66413e97 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "shm.h"
 #include <unistd.h>
+#include <string.h>
 #include <fcntl.h>
 #include <sys/mman.h>
 #include <sys/stat.h>  /* For mode constants */
@@ -32,6 +33,8 @@
 #include <helper.h>
 #include <limits.h>
 #include <helper.h>
+/* FIXME: Include UUID the proper way, e.g. config.h... */
+#include <uuid/uuid.h>
 
 /*
  * Ensure we have the required amount of space available by writing 0
@@ -81,39 +84,95 @@ struct shm_object_table *shm_object_table_create(size_t max_nb_obj)
        return table;
 }
 
+/*
+ * Generate a unique name with the desired prefix.
+ * Pattern is as follow: prefix-pid-uuid.
+ * Caller is responsible of freeing the resulting string.
+ */
+static
+char *gen_unique_name(const char *prefix)
+{
+       int written;
+       pid_t pid;
+       uuid_t uuid;
+       char uuid_str[37];
+       char tmp_name[NAME_MAX];
+       char *name;
+
+       if (!prefix)
+               return NULL;
+
+       pid = getpid();
+
+       uuid_generate(uuid);
+       uuid_unparse(uuid, uuid_str);
+
+       written = snprintf(tmp_name, NAME_MAX,
+                          "%s-%d-%s", prefix, pid, uuid_str);
+
+       if (written < 0 || written >= NAME_MAX)
+               return NULL;
+
+       name = zmalloc(written + 1);
+
+       if (!name)
+               return NULL;
+
+       return strncpy(name, tmp_name, written);
+}
+
 struct shm_object *shm_object_table_append(struct shm_object_table *table,
                                           size_t memory_map_size)
 {
-       int shmfd, waitfd[2], ret, i, sigblocked = 0;
+       int shmfd, ret, sigblocked = 0;
        struct shm_object *obj;
        char *memory_map;
+
+       const char *base_shm      = "/dev/shm/";
+       const char *base_path     = "/tmp/lttng-fds/";
+       const char *waitfd_prefix = "ust-wait";
+       const char *shm_prefix    = "ust-shm";
+
+       char *wait_pipe_path, *wait_pipe_file;
+       char *shm_path, *shm_symlink_path, *shm_file;
+
        char tmp_name[NAME_MAX] = "ust-shm-tmp-XXXXXX";
+
        sigset_t all_sigs, orig_sigs;
 
        if (table->allocated_len >= table->size)
                return NULL;
        obj = &table->objects[table->allocated_len];
 
-       /* wait_fd: create pipe */
-       ret = pipe(waitfd);
-       if (ret < 0) {
-               PERROR("pipe");
-               goto error_pipe;
+       wait_pipe_file = gen_unique_name(waitfd_prefix);
+
+       if (!wait_pipe_file) {
+               goto error_gen_unique_wait;
        }
-       for (i = 0; i < 2; i++) {
-               ret = fcntl(waitfd[i], F_SETFD, FD_CLOEXEC);
-               if (ret < 0) {
-                       PERROR("fcntl");
-                       goto error_fcntl;
-               }
+
+       wait_pipe_path = zmalloc(strlen(base_path)
+                                + strlen(wait_pipe_file) + 1);
+
+       if (!wait_pipe_path) {
+               free(wait_pipe_file);
+               goto error_wait_alloc;
        }
-       /* The write end of the pipe needs to be non-blocking */
-       ret = fcntl(waitfd[1], F_SETFL, O_NONBLOCK);
+
+       strncat(wait_pipe_path, base_path, strlen(base_path));
+       strncat(wait_pipe_path, wait_pipe_file, strlen(wait_pipe_file));
+
+       free(wait_pipe_file);
+
+       /* wait_fd: create named pipe */
+       ret = mkfifo(wait_pipe_path, 0777);
        if (ret < 0) {
-               PERROR("fcntl");
-               goto error_fcntl;
+               PERROR("mkfifo");
+               goto error_mkfifo;
        }
-       memcpy(obj->wait_fd, waitfd, sizeof(waitfd));
+
+       obj->wait_fd[0] = -1;
+       obj->wait_fd[1] = -1;
+       obj->wait_pipe_path = wait_pipe_path;
 
        /* shm_fd: create shm */
 
@@ -131,10 +190,6 @@ struct shm_object *shm_object_table_append(struct shm_object_table *table,
        sigblocked = 1;
 
        /*
-        * Allocate shm, and immediately unlink its shm oject, keeping
-        * only the file descriptor as a reference to the object. If it
-        * already exists (caused by short race window during which the
-        * global object exists in a concurrent shm_open), simply retry.
         * We specifically do _not_ use the / at the beginning of the
         * pathname so that some OS implementations can keep it local to
         * the process (POSIX leaves this implementation-defined).
@@ -156,17 +211,54 @@ struct shm_object *shm_object_table_append(struct shm_object_table *table,
                PERROR("shm_open");
                goto error_shm_open;
        }
-       ret = shm_unlink(tmp_name);
-       if (ret < 0 && errno != ENOENT) {
-               PERROR("shm_unlink");
-               goto error_shm_release;
-       }
+
        sigblocked = 0;
        ret = pthread_sigmask(SIG_SETMASK, &orig_sigs, NULL);
        if (ret == -1) {
                PERROR("pthread_sigmask");
                goto error_sigmask_release;
        }
+
+       /* Create unique symlink to shm */
+       shm_path = zmalloc(strlen(base_shm) + strlen(tmp_name) + 1);
+
+       if (!shm_path) {
+               goto error_shm_alloc;
+       }
+
+       strncat(shm_path, base_shm, strlen(base_shm));
+       strncat(shm_path, tmp_name, strlen(tmp_name));
+
+       shm_file = gen_unique_name(shm_prefix);
+
+       if (!shm_file) {
+               free(shm_path);
+               goto error_gen_unique_shm;
+       }
+
+       shm_symlink_path = zmalloc(strlen(base_path) + strlen(shm_file) + 1);
+
+       if (!shm_symlink_path) {
+               free(shm_path);
+               free(shm_file);
+               goto error_symlink_alloc;
+       }
+
+       strncat(shm_symlink_path, base_path, strlen(base_path));
+       strncat(shm_symlink_path, shm_file, strlen(shm_file));
+
+       free(shm_file);
+
+       ret = symlink(shm_path, shm_symlink_path);
+       if (ret < 0) {
+               PERROR("symlink");
+               free(shm_path);
+               free(shm_symlink_path);
+               goto error_symlink_shm;
+       }
+
+       free(shm_path);
+
        ret = zero_file(shmfd, memory_map_size);
        if (ret) {
                PERROR("zero_file");
@@ -178,6 +270,7 @@ struct shm_object *shm_object_table_append(struct shm_object_table *table,
                goto error_ftruncate;
        }
        obj->shm_fd = shmfd;
+       obj->shm_path = shm_symlink_path;
 
        /* memory_map: mmap */
        memory_map = mmap(NULL, memory_map_size, PROT_READ | PROT_WRITE,
@@ -195,8 +288,12 @@ struct shm_object *shm_object_table_append(struct shm_object_table *table,
 
 error_mmap:
 error_ftruncate:
-error_shm_release:
 error_zero_file:
+       free(shm_symlink_path);
+error_symlink_shm:
+error_symlink_alloc:
+error_gen_unique_shm:
+error_shm_alloc:
 error_sigmask_release:
        ret = close(shmfd);
        if (ret) {
@@ -211,17 +308,11 @@ error_shm_open:
                }
        }
 error_pthread_sigmask:
-error_fcntl:
-       for (i = 0; i < 2; i++) {
-               ret = close(waitfd[i]);
-               if (ret) {
-                       PERROR("close");
-                       assert(0);
-               }
-       }
-error_pipe:
+error_mkfifo:
+       free(wait_pipe_path);
+error_wait_alloc:
+error_gen_unique_wait:
        return NULL;
-       
 }
 
 struct shm_object *shm_object_table_append_shadow(struct shm_object_table *table,
@@ -276,6 +367,11 @@ void shmp_object_destroy(struct shm_object *obj)
                        assert(0);
                }
        }
+
+       if (obj->shm_path) {
+               free(obj->shm_path);
+       }
+
        for (i = 0; i < 2; i++) {
                if (obj->wait_fd[i] < 0)
                        continue;
@@ -285,6 +381,10 @@ void shmp_object_destroy(struct shm_object *obj)
                        assert(0);
                }
        }
+
+       if (obj->wait_pipe_path) {
+               free(obj->wait_pipe_path);
+       }
 }
 
 void shm_object_table_destroy(struct shm_object_table *table)
index 8987f72a30f3dc234cf2ca9d7b777c86b6197cf3..a745d34592bab4b962990b6a90255b3e74e60222 100644 (file)
@@ -119,7 +119,9 @@ int shm_get_wait_fd(struct lttng_ust_shm_handle *handle, struct shm_ref *ref)
 
 static inline
 int shm_get_object_data(struct lttng_ust_shm_handle *handle, struct shm_ref *ref,
-               int **shm_fd, int **wait_fd, uint64_t **memory_map_size)
+                       int **shm_fd, char **shm_path,
+                       int **wait_fd, char **wait_pipe_path,
+                       uint64_t **memory_map_size)
 {
        struct shm_object_table *table = handle->table;
        struct shm_object *obj;
@@ -129,8 +131,10 @@ int shm_get_object_data(struct lttng_ust_shm_handle *handle, struct shm_ref *ref
        if (caa_unlikely(index >= table->allocated_len))
                return -EPERM;
        obj = &table->objects[index];
-       *shm_fd = &obj->shm_fd;
-       *wait_fd = &obj->wait_fd[0];
+       *shm_fd   = &obj->shm_fd;
+       *shm_path = obj->shm_path;
+       *wait_fd        = &obj->wait_fd[0];
+       *wait_pipe_path = obj->wait_pipe_path;
        *memory_map_size = &obj->allocated_len;
        return 0;
 }
index 8b01d803e8ad4c2189f8bf40dbbab0bf9188511a..a311f1cdd0adf7aea3fcbb8cfd6f1cd7eb47c1a5 100644 (file)
 struct channel;
 
 struct shm_object {
-       size_t index;   /* within the object table */
-       int shm_fd;     /* shm fd */
-       int wait_fd[2]; /* fd for wait/wakeup */
+       size_t index;         /* within the object table */
+       int shm_fd;           /* shm fd */
+       char *shm_path;       /* shm path */
+       int wait_fd[2];       /* fd for wait/wakeup */
+       char *wait_pipe_path; /* named pipe path for wait/wakeup */
        char *memory_map;
        int is_shadow;
        size_t memory_map_size;
index e704af1f9e346768f310bcbc9479fd80f2a56c5a..186d56ef4e3a37b851008acc51c50730ca54bc60 100644 (file)
@@ -207,13 +207,17 @@ int consume_stream(struct lttng_ust_shm_handle *handle, int cpu, char *outfile)
        struct lttng_ust_lib_ring_buffer *buf;
        int outfd, ret;
        int *shm_fd, *wait_fd;
+       char *shm_path, *wait_pipe_path;
        uint64_t *memory_map_size;
 
        chan = shmp(handle, handle->chan);
 
        /* open stream */
        buf = channel_get_ring_buffer(&chan->backend.config,
-               chan, cpu, handle, &shm_fd, &wait_fd, &memory_map_size);
+                                     chan, cpu, handle,
+                                     &shm_fd, &shm_path,
+                                     &wait_fd, &wait_pipe_path,
+                                     &memory_map_size);
        if (!buf)
                return -ENOENT;
        ret = lib_ring_buffer_open_read(buf, handle, 1);
index bea01b168c447c98c34517164adfeebbfca21e12..db62962689ae21f07a906011246ea04a01187083 100644 (file)
@@ -214,13 +214,17 @@ int consume_stream(struct lttng_ust_shm_handle *handle, int cpu, char *outfile)
        struct lttng_ust_lib_ring_buffer *buf;
        int outfd, ret;
        int *shm_fd, *wait_fd;
+       char *shm_path, *wait_pipe_path;
        uint64_t *memory_map_size;
 
        chan = shmp(handle, handle->chan);
 
        /* open stream */
        buf = channel_get_ring_buffer(&chan->backend.config,
-               chan, cpu, handle, &shm_fd, &wait_fd, &memory_map_size);
+                                     chan, cpu, handle,
+                                     &shm_fd, &shm_path,
+                                     &wait_fd, &wait_pipe_path,
+                                     &memory_map_size);
        if (!buf)
                return -ENOENT;
        ret = lib_ring_buffer_open_read(buf, handle, 1);
This page took 0.041102 seconds and 4 git commands to generate.