Cygwin: Introduce new LTTNG_UST_STREAM_PIPE command to open wakeup pipe
authorChristian Babeux <christian.babeux@efficios.com>
Thu, 29 Nov 2012 02:11:27 +0000 (21:11 -0500)
committerChristian Babeux <christian.babeux@efficios.com>
Thu, 29 Nov 2012 02:14:14 +0000 (21:14 -0500)
Normally, the userspace tracer open the wakeup pipe, and the resulting
fd is passed to the consumer via the session daemon. Since we can't pass
fds via UNIX socket, the pipe need to be opened separately in the tracer
and in the consumer. The only way to open the write side of a named pipe
*before* the read side without blocking is to open it in read/write mode.
This is supported on Linux, but POSIX leave this behavior undefined [1].

The Cygwin named pipe implementation doesn't seem to allow multiple
readers/writers on a named pipe. Opening a pipe in RW mode in the tracer
and then opening the read side in the consumer won't work because the
consumer will get a "Device or ressource busy" error. Thus arise the need
to open the named pipe read side *before* the write side.

In order to accomplish this task, a new command must be introduced to signal
to the tracer that a specific named pipe should be opened in write mode.

Proper care must be taken to issue this command *after* the named pipe paths
have been sent to the consumer or else the sessiond or tracer will block
indefinitely.

[1] - man 7 fifo

include/lttng/ust-abi.h
include/lttng/ust-ctl.h
include/lttng/ust-events.h
liblttng-ust-ctl/ustctl.c
liblttng-ust/ltt-ring-buffer-client.h
liblttng-ust/ltt-ring-buffer-metadata-client.h
liblttng-ust/lttng-ust-abi.c
libringbuffer/shm.h

index 86edba90f8134bbc2cb28941fda01f51246b4e99..cc9fa76a5f9b9f3a1bf7087f1120ab15d17ad57d 100644 (file)
@@ -179,7 +179,7 @@ struct lttng_ust_calibrate {
 #define LTTNG_UST_STREAM                       _UST_CMD(0x60)
 #define LTTNG_UST_EVENT                        \
        _UST_CMDW(0x61, struct lttng_ust_event)
-
+#define LTTNG_UST_STREAM_PIPE                  _UST_CMD(0x62)
 /* Event and Channel FD commands */
 #define LTTNG_UST_CONTEXT                      \
        _UST_CMDW(0x70, struct lttng_ust_context)
index 10602ee73c4d3cf66433549b213c6c03ca6f2531..8917d0e0e4c9af33e944c4d3713f97a40a1ec743 100644 (file)
@@ -26,6 +26,7 @@ int ustctl_create_session(int sock);
 int ustctl_open_metadata(int sock, int session_handle,
                struct lttng_ust_channel_attr *chops,
                struct lttng_ust_object_data **metadata_data);
+int ustctl_open_wait_pipe(int sock, struct lttng_ust_object_data *channel_data);
 int ustctl_create_channel(int sock, int session_handle,
                struct lttng_ust_channel_attr *chops,
                struct lttng_ust_object_data **channel_data);
index b892fbf84f7190e273ad866fcd54b30870d70ac0..1044bb0a7834a972771cd8c6cc4b792883c71fe3 100644 (file)
@@ -332,6 +332,7 @@ struct ltt_channel_ops {
        int (*is_finalized)(struct channel *chan);
        int (*is_disabled)(struct channel *chan);
        int (*flush_buffer)(struct channel *chan, struct lttng_ust_shm_handle *handle);
+       int (*channel_open_pipe)(struct channel *chan, struct lttng_ust_shm_handle *handle);
 };
 
 struct ltt_channel {
index 5069fbb19ce9638de182540c8c4a235ed61171d9..c9e930d045916b82eb7234ca80c07532aab0126e 100644 (file)
@@ -237,6 +237,36 @@ error:
        return -EINVAL;
 }
 
+int ustctl_open_wait_pipe(int sock,
+                         struct lttng_ust_object_data *channel_data)
+{
+       struct ustcomm_ust_msg lum;
+       struct ustcomm_ust_reply lur;
+       int ret;
+
+       if (!channel_data)
+               return -EINVAL;
+
+       /* Create metadata channel */
+       memset(&lum, 0, sizeof(lum));
+       lum.handle = channel_data->handle;
+       lum.cmd = LTTNG_UST_STREAM_PIPE;
+       ret = ustcomm_send_app_cmd(sock, &lum, &lur);
+
+       if (ret) {
+               goto error;
+       }
+       if (lur.ret_code != USTCOMM_OK) {
+               ret = lur.ret_code;
+               goto error;
+       }
+
+       return 0;
+
+error:
+       return ret;
+}
+
 int ustctl_create_channel(int sock, int session_handle,
                struct lttng_ust_channel_attr *chops,
                struct lttng_ust_object_data **_channel_data)
index b896169e0f64d4257cd46844252e46764b063e4a..0779348ac28fcebb60d697a2dba2175738d3aebd 100644 (file)
@@ -437,6 +437,34 @@ struct ltt_channel *_channel_create(const char *name,
        return ltt_chan;
 }
 
+static
+int ltt_channel_open_pipe(struct channel *chan,
+                         struct lttng_ust_shm_handle *handle)
+{
+       struct shm_ref *ref;
+       int cpu = 0;
+
+       if (client_config.alloc == RING_BUFFER_ALLOC_GLOBAL) {
+               ref = &chan->backend.buf[0].shmp._ref;
+               return shm_open_wakeup_pipe(handle, ref);
+       } else {
+               if (cpu >= num_possible_cpus()) {
+                       goto error;
+               }
+
+               for_each_possible_cpu(cpu) {
+                       ref = &chan->backend.buf[cpu].shmp._ref;
+                       if (shm_open_wakeup_pipe(handle, ref) < 0) {
+                               goto error;
+                       }
+               }
+       }
+
+       return 0;
+error:
+       return -1;
+}
+
 static
 void ltt_channel_destroy(struct ltt_channel *ltt_chan)
 {
@@ -571,6 +599,7 @@ static struct ltt_transport ltt_relay_transport = {
        .name = "relay-" RING_BUFFER_MODE_TEMPLATE_STRING "-mmap",
        .ops = {
                .channel_create = _channel_create,
+               .channel_open_pipe = ltt_channel_open_pipe,
                .channel_destroy = ltt_channel_destroy,
                .buffer_read_open = ltt_buffer_read_open,
                .buffer_read_close = ltt_buffer_read_close,
index 0e9b7fa3f2f3f544158f72b9aed48ca2526d764b..a8ba282d8cbebf1a8ed28677bb808bef3f164ee1 100644 (file)
@@ -207,6 +207,34 @@ struct ltt_channel *_channel_create(const char *name,
        return ltt_chan;
 }
 
+static
+int ltt_channel_open_pipe(struct channel *chan,
+                         struct lttng_ust_shm_handle *handle)
+{
+       struct shm_ref *ref;
+       int cpu = 0;
+
+       if (client_config.alloc == RING_BUFFER_ALLOC_GLOBAL) {
+               ref = &chan->backend.buf[0].shmp._ref;
+               return shm_open_wakeup_pipe(handle, ref);
+       } else {
+               if (cpu >= num_possible_cpus()) {
+                       goto error;
+               }
+
+               for_each_possible_cpu(cpu) {
+                       ref = &chan->backend.buf[cpu].shmp._ref;
+                       if (shm_open_wakeup_pipe(handle, ref) < 0) {
+                               goto error;
+                       }
+               }
+       }
+
+       return 0;
+error:
+       return -1;
+}
+
 static
 void ltt_channel_destroy(struct ltt_channel *ltt_chan)
 {
@@ -321,6 +349,7 @@ static struct ltt_transport ltt_relay_transport = {
        .name = "relay-" RING_BUFFER_MODE_TEMPLATE_STRING "-mmap",
        .ops = {
                .channel_create = _channel_create,
+               .channel_open_pipe = ltt_channel_open_pipe,
                .channel_destroy = ltt_channel_destroy,
                .buffer_read_open = ltt_buffer_read_open,
                .buffer_read_close = ltt_buffer_read_close,
index a3edd3ead7d93343c26fd1067449f98713658cb9..c0e089d0022b5362dc44b477c5349bdb08d553dd 100644 (file)
@@ -783,6 +783,8 @@ long lttng_channel_cmd(int objd, unsigned int cmd, unsigned long arg,
                return ltt_channel_disable(channel);
        case LTTNG_UST_FLUSH_BUFFER:
                return channel->ops->flush_buffer(channel->chan, channel->handle);
+       case LTTNG_UST_STREAM_PIPE:
+               return channel->ops->channel_open_pipe(channel->chan, channel->handle);
        default:
                return -EINVAL;
        }
@@ -819,6 +821,8 @@ long lttng_metadata_cmd(int objd, unsigned int cmd, unsigned long arg,
        }
        case LTTNG_UST_FLUSH_BUFFER:
                return channel->ops->flush_buffer(channel->chan, channel->handle);
+       case LTTNG_UST_STREAM_PIPE:
+               return channel->ops->channel_open_pipe(channel->chan, channel->handle);
        default:
                return -EINVAL;
        }
index a745d34592bab4b962990b6a90255b3e74e60222..3a61a39d5e1d86a77d1df100017fe12b7a737ff1 100644 (file)
@@ -25,6 +25,7 @@
 #include <usterr-signal-safe.h>
 #include <urcu/compiler.h>
 #include "shm_types.h"
+#include <fcntl.h>
 
 /*
  * Pointer dereferencing. We don't trust the shm_ref, so we validate
@@ -99,8 +100,37 @@ int shm_get_wakeup_fd(struct lttng_ust_shm_handle *handle, struct shm_ref *ref)
        if (caa_unlikely(index >= table->allocated_len))
                return -EPERM;
        obj = &table->objects[index];
+
        return obj->wait_fd[1];
+}
+
+static inline
+int shm_open_wakeup_pipe(struct lttng_ust_shm_handle *handle, struct shm_ref *ref)
+{
+       struct shm_object_table *table = handle->table;
+       struct shm_object *obj;
+       size_t index;
+       int fd, ret = -1;
+
+       index = (size_t) ref->index;
+       if (caa_unlikely(index >= table->allocated_len))
+               return -EPERM;
+
+       obj = &table->objects[index];
 
+       if (obj->wait_fd[1] < 0 && obj->wait_pipe_path != NULL) {
+               fd = open(obj->wait_pipe_path, O_WRONLY);
+               if (fd < 0) {
+                       ret = -1;
+               } else {
+                       /* FIXME: What if fcntl fail? */
+                       fcntl(fd, F_SETFD, FD_CLOEXEC);
+                       obj->wait_fd[1] = fd;
+                       ret = 0;
+               }
+       }
+
+       return ret;
 }
 
 static inline
This page took 0.029306 seconds and 4 git commands to generate.