posix_mq RubyGem user+dev discussion/patches/pulls/bugs/help
 help / color / mirror / code / Atom feed
Search results ordered by [date|relevance]  view[summary|nested|Atom feed]
thread overview below | download mbox.gz: |
* [ANN] posix_mq 2.2.0 - POSIX Message Queues for Ruby
@ 2015-01-16 20:32  4% Eric Wong
  0 siblings, 0 replies; 5+ results
From: Eric Wong @ 2015-01-16 20:32 UTC (permalink / raw)
  To: ruby-talk, ruby-posix-mq; +Cc: Christopher Lord

POSIX message queues allow local processes to exchange data in the form
of messages.  This API is distinct from that provided by System V
message queues, but provides similar functionality.

* Homepage: http://bogomips.org/ruby_posix_mq/
* public-inbox: ruby-posix-mq@bogomips.org
* git clone git://bogomips.org/ruby_posix_mq.git
* Atom feed: http://bogomips.org/ruby_posix_mq/NEWS.atom.xml
* Mailing list archives: http://bogomips.org/ruby-posix-mq/

Changes:

The major feature of this release is the POSIX_MQ.for_fd class
method thanks to Christopher Lord.  The addition of the
POSIX_MQ#autoclose? and POSIX_MQ#autoclose= round out the new
feature set.  All of the new methods are analogous to their
counterparts in the core IO class.

The mailing list is also moved to ruby-posix-mq@bogomips.org
and no longer requires subscription.  Existing librelist
subscribers will need to resubscribe manually (as I have no
way of doing so automatically):

	ruby-posix-mq+subscribe@bogomips.org

HTTP archives and instructions for extracting the mail archives
via git are available at:

	http://bogomips.org/ruby-posix-mq/

Christopher Lord (1):
      Ability to adopt file descriptors

Eric Wong (16):
      for_fd: delay assigning to mq->des until after mq_getattr
      test_posix_mq: rewrite test to not depend on DL or alarm
      support autoclose= and autoclose?
      pack rw_args struct
      change mailing list to ruby-posix-mq@bogomips.org
      doc: remove --sanitize-html option for pandoc
      switch documentation to olddoc
      LICENSE: allow all future versions of LGPLv3+
      favor comparisons against zero instead of -1
      pkg.mk: misc tweaks and updates
      gemspec: remove rdoc_options setting
      .gitignore: add placeholder
      gemspec: use SPDX license abbreviation
      misc doc updates
      POSIX_MQ#autoclose= propagates to IO
      GNUmakefile: ordering fix for building gem
-- 
EW

^ permalink raw reply	[relevance 4%]

* Re: [PATCH] Ability to adopt file descriptors
  2015-01-04  3:34  5%   ` Christopher Lord
@ 2015-01-05  5:34  7%     ` Eric Wong
  0 siblings, 0 replies; 5+ results
From: Eric Wong @ 2015-01-05  5:34 UTC (permalink / raw)
  To: ruby.posix.mq

Christopher Lord <christopher@lord.ac> wrote:
> That said, I was sure I double-checked that 
> 
> 	X.class.method_defined?(a) == X.respond_to?(a)
>
> Perhaps there is a difference between versions? or is this just a
> stylistic preference? anyway no problem if you want to change that
> too.

	POSIX_MQ.class == Class

So I'm not sure what you were testing :)
I think every version of Ruby behaves that way.

Anyways, I pushed out
http://bogomips.org/ruby_posix_mq.git/patch?id=6622d115

I'll work on documentation + website + mailing list updates
(affects a bunch of my projects actually) and hopefully have a
new release in a few days.

> I suspect autoclose might be useful for other uses of the change than
> systemd socket activation. I know autoclose can be useful for evented
> code or in situations where the wrapper socket type is ephemerally
> recreated after going through non-ruby extensions to save memory. I
> can imagine someone wanting to do something similar with message
> queues, so autoclose might be useful there.

Yep.  If you have spare cyclesk, a patch for autoclose=/autoclose? would
be appreciated, otherwise I can take care of it.

Also, I've been meaning to add an "or later" clause to the current
LGPLv3 license.  Are you OK with that?
This is in case I'm hit by a bus and the FSF comes out with LGPLv4,
I want to make sure the project can upgrade.


^ permalink raw reply	[relevance 7%]

* Re: [PATCH] Ability to adopt file descriptors
  2015-01-04  1:16  5% ` Eric Wong
@ 2015-01-04  3:34  5%   ` Christopher Lord
  2015-01-05  5:34  7%     ` Eric Wong
  0 siblings, 1 reply; 5+ results
From: Christopher Lord @ 2015-01-04  3:34 UTC (permalink / raw)
  To: ruby.posix.mq

Hello, thanks for the review! Basically I wanted to upstream some local changes I had made for an internal project, so 'cleaned up' a patch. A lot of your code review boils down to “I should have put more effort/testing into the 'cleaned up’ version” :)  Always embarrassing. Comments below:

> Hi Christopher, this seems useful, thanks!  I have some comments below,
> but I'll queue it up with my changes so you don't have to resend
> (unless you have objections to my changes)

No major objections, am ok with that.

> 
>> +static VALUE for_fd(VALUE klass, VALUE socket)
>> +{
>> +	VALUE mqv = alloc(klass);
>> +	struct posix_mq *mq = get(mqv, 0);
>> +
>> +	mq->name = Qnil;
>> +
>> +	if (rb_respond_to(socket, id_to_i)) {
>> +		VALUE fd_num = rb_funcall(socket, id_to_i, 0);
>> +		mq->des = FD_TO_MQD(NUM2INT(fd_num));
>> +	}
> 
> Probably better to skip the to_i conversion to match IO.for_fd
> semantics.  No need to define and use id_to_i anymore.

I had it like that originally, but ended up changing to the to_i version in the ‘cleaned up’ version because it seemed cool. I am perfectly fine with being consistent with IO, thanks for catching that.

> 
>> +	else {
>> +		rb_raise(rb_eArgError, "provided argument must be (or convertable to) an integer file descriptor");
> 
> will raise TypeError instead of ArgumentError to be consistent with IO

Yes, that’s message is a TypeError, not an ArgError. I like your version.

> 
>> +	if (mq->des < 0) {
>> +		rb_raise(rb_eArgError, "provided argument must be a valid file descriptor");
>> +	}
> 
> This (mq->des < 0) check is unnecessary since we check with mq_getattr
> anyways.  It should be as consistent as possible with the way IO.for_fd
> works.

Artifact of my cleanup effort. Agreed that it’s (mostly) duplicated.

> 
>> +	if (mq_getattr(mq->des, &mq->attr) < 0) {
>> +		if (errno) {
>> +			rb_raise(rb_eArgError, "provided file descriptor is not a POSIX message queue");
>> +		}
> 
> This should be:
> 
> 		rb_sys_fail("provided file descriptor is not a POSIX MQ");
> 
> We should not expect errno to be zero if mq_getattr returns < 0

I modelled the check above on the dbus/systemd code[1] (sd_is_mq) that checks that a file descriptor is a posix mq. It checks both the return being less than zero, and that the errno is non-zero. Presumably it’s because it’s to ensure the sequence point exists between mq_getattr and errno, but honestly it shouldn’t matter. if mq_getattr returns less-than-zero, then surely the errno was set as well. Either way is fine by me.

[1]: http://dbus.freedesktop.org/doc/api/html/sd-daemon_8c_source.html

> 
> Rest of the C code looks fine; I'll wrap the long lines before pushing.
> 
> However, the test code has me worried:
> 
>> --- a/test/test_posix_mq.rb
>> +++ b/test/test_posix_mq.rb
>> @@ -17,6 +17,8 @@ class Test_POSIX_MQ < Test::Unit::TestCase
>>    warn "POSIX_MQ#to_io not supported on this platform: #{RUBY_PLATFORM}"
>>  POSIX_MQ.method_defined?(:notify) or
>>    warn "POSIX_MQ#notify not supported on this platform: #{RUBY_PLATFORM}"
>> +  POSIX_MQ.class.method_defined?(:for_fd) or
>> +    warn "POSIX_MQ::for_fd not supported on this platform: #{RUBY_PLATFORM}"
>> 
>>  def setup
>>    @mq = nil
>> @@ -244,6 +246,17 @@ class Test_POSIX_MQ < Test::Unit::TestCase
>>    assert_nothing_raised { IO.select([@mq], nil, nil, 0) }
>>  end if POSIX_MQ.method_defined?(:to_io)
>> 
>> +  def test_for_fd
>> +    @mq = POSIX_MQ.new @path, IO::CREAT|IO_RDWR, 0666
>> +    @alt = POSIX_MQ.for_fd(@mq.to_io.to_i)
>> +    assert_equal true, @mq.send("hello", 0)
>> +    assert_equal [ "hello", 0 ], @alt.receive(buf)
>> +    assert_equal "hello", buf
>> +    assert_equal @mq.to_io.to_i, @alt.to_io.to_i
>> +    assert_raises(ArgumentError) { @alt.name }
>> +    assert_raises(ArgumentError) { POSIX_MQ.for_fd(1) }
>> +  end if POSIX_MQ.class.method_defined?(:for_fd) && POSIX_MQ.method_defined(:to_io)
> 
> I'm not sure how you managed to run your new test at all,

Yep, you caught me. wrote the tests without running them and missed `buff = “"`. I had a version mismatch between my ruby’s minitest and the one used to run the tests in this project. I ran the tests in irb and then tried to make double-sure the testcase was perfect because I didn’t want to change the underlying dependency and screw you guys up. That said, I was sure I double-checked that 

	X.class.method_defined?(a) == X.respond_to?(a)

Perhaps there is a difference between versions? or is this just a stylistic preference? anyway no problem if you want to change that too.

> I think the following is needed:
> 
> --- a/test/test_posix_mq.rb
> +++ b/test/test_posix_mq.rb
> @@ -17,7 +17,7 @@ class Test_POSIX_MQ < Test::Unit::TestCase
>    warn "POSIX_MQ#to_io not supported on this platform: #{RUBY_PLATFORM}"
>  POSIX_MQ.method_defined?(:notify) or
>    warn "POSIX_MQ#notify not supported on this platform: #{RUBY_PLATFORM}"
> -  POSIX_MQ.class.method_defined?(:for_fd) or
> +  POSIX_MQ.respond_to?(:for_fd) or
>    warn "POSIX_MQ::for_fd not supported on this platform: #{RUBY_PLATFORM}"
> 
>  def setup
> @@ -247,7 +247,8 @@ class Test_POSIX_MQ < Test::Unit::TestCase
>  end if POSIX_MQ.method_defined?(:to_io)
> 
>  def test_for_fd
> -    @mq = POSIX_MQ.new @path, IO::CREAT|IO_RDWR, 0666
> +    buf = ""
> +    @mq = POSIX_MQ.new @path, IO::CREAT|IO::RDWR, 0666
>    @alt = POSIX_MQ.for_fd(@mq.to_io.to_i)
>    assert_equal true, @mq.send("hello", 0)
>    assert_equal [ "hello", 0 ], @alt.receive(buf)
> @@ -255,7 +256,7 @@ class Test_POSIX_MQ < Test::Unit::TestCase
>    assert_equal @mq.to_io.to_i, @alt.to_io.to_i
>    assert_raises(ArgumentError) { @alt.name }
>    assert_raises(ArgumentError) { POSIX_MQ.for_fd(1) }
> -  end if POSIX_MQ.class.method_defined?(:for_fd) && POSIX_MQ.method_defined(:to_io)
> +  end if POSIX_MQ.respond_to?(:for_fd) && POSIX_MQ.method_defined?(:to_io)
> 
>  def test_notify
>    rd, wr = IO.pipe


> Also, I think we'll also need to support equivalents of IO#autoclose?
> and IO#autoclose=, because having two POSIX_MQ objects refer to the same
> FD will cause problems with the GC performing auto-close by default.

I suspect autoclose might be useful for other uses of the change than systemd socket activation. I know autoclose can be useful for evented code or in situations where the wrapper socket type is ephemerally recreated after going through non-ruby extensions to save memory. I can imagine someone wanting to do something similar with message queues, so autoclose might be useful there.




^ permalink raw reply	[relevance 5%]

* Re: [PATCH] Ability to adopt file descriptors
  2015-01-03 17:15  3% [PATCH] Ability to adopt file descriptors Christopher Lord
@ 2015-01-04  1:16  5% ` Eric Wong
  2015-01-04  3:34  5%   ` Christopher Lord
  0 siblings, 1 reply; 5+ results
From: Eric Wong @ 2015-01-04  1:16 UTC (permalink / raw)
  To: ruby.posix.mq

Christopher Lord <christopher@lord.ac> wrote:
> This patch adds support for adopting an existing file descriptor, together
> with testcases. The need for this comes up when we use systemd with the
> ListenMessageQueue directive. For socket activation, systemd opens the POSIX
> message queue and expects user code to begin using the file descriptor
> without opening it in-process.
> 
> To support the systemd model in the `posix_mq` gem, this patch suggests
> imitating the behavior on the Socket class, which uses `#for_fd` to create a
> socket class from a descriptor.

Hi Christopher, this seems useful, thanks!  I have some comments below,
but I'll queue it up with my changes so you don't have to resend
(unless you have objections to my changes)

> One confounding factor exists. POSIX queues have a name but it is difficult
> to get access to this name in a safe manner from the file descriptor. One
> option would be to `readlink(2)` on `/proc/self/fd/N` to get the name[1], but
> note that if the descriptor is unlinked we wouldn't get anything usable.
> Rather than risk incorrect behavior and extra complexity, I've decided to
> just raise an `ArgumentError` if `#name` is called on adopted descriptors.
> Typically one wouldn't need the actual name in a systemd socket-activated
> situation, anyway.

That's fine.

> +static VALUE for_fd(VALUE klass, VALUE socket)
> +{
> +	VALUE mqv = alloc(klass);
> +	struct posix_mq *mq = get(mqv, 0);
> +
> +	mq->name = Qnil;
> +
> +	if (rb_respond_to(socket, id_to_i)) {
> +		VALUE fd_num = rb_funcall(socket, id_to_i, 0);
> +		mq->des = FD_TO_MQD(NUM2INT(fd_num));
> +	}

Probably better to skip the to_i conversion to match IO.for_fd
semantics.  No need to define and use id_to_i anymore.

	mq->des = FD_TO_MQD(NUM2INT(fd_num));

So the below:

> +	else {
> +		rb_raise(rb_eArgError, "provided argument must be (or convertable to) an integer file descriptor");

will raise TypeError instead of ArgumentError to be consistent with IO

> +	if (mq->des < 0) {
> +		rb_raise(rb_eArgError, "provided argument must be a valid file descriptor");
> +	}

This (mq->des < 0) check is unnecessary since we check with mq_getattr
anyways.  It should be as consistent as possible with the way IO.for_fd
works.

> +	if (mq_getattr(mq->des, &mq->attr) < 0) {
> +		if (errno) {
> +			rb_raise(rb_eArgError, "provided file descriptor is not a POSIX message queue");
> +		}

This should be:

		rb_sys_fail("provided file descriptor is not a POSIX MQ");

We should not expect errno to be zero if mq_getattr returns < 0

Rest of the C code looks fine; I'll wrap the long lines before pushing.

However, the test code has me worried:

> --- a/test/test_posix_mq.rb
> +++ b/test/test_posix_mq.rb
> @@ -17,6 +17,8 @@ class Test_POSIX_MQ < Test::Unit::TestCase
>      warn "POSIX_MQ#to_io not supported on this platform: #{RUBY_PLATFORM}"
>    POSIX_MQ.method_defined?(:notify) or
>      warn "POSIX_MQ#notify not supported on this platform: #{RUBY_PLATFORM}"
> +  POSIX_MQ.class.method_defined?(:for_fd) or
> +    warn "POSIX_MQ::for_fd not supported on this platform: #{RUBY_PLATFORM}"
>  
>    def setup
>      @mq = nil
> @@ -244,6 +246,17 @@ class Test_POSIX_MQ < Test::Unit::TestCase
>      assert_nothing_raised { IO.select([@mq], nil, nil, 0) }
>    end if POSIX_MQ.method_defined?(:to_io)
>  
> +  def test_for_fd
> +    @mq = POSIX_MQ.new @path, IO::CREAT|IO_RDWR, 0666
> +    @alt = POSIX_MQ.for_fd(@mq.to_io.to_i)
> +    assert_equal true, @mq.send("hello", 0)
> +    assert_equal [ "hello", 0 ], @alt.receive(buf)
> +    assert_equal "hello", buf
> +    assert_equal @mq.to_io.to_i, @alt.to_io.to_i
> +    assert_raises(ArgumentError) { @alt.name }
> +    assert_raises(ArgumentError) { POSIX_MQ.for_fd(1) }
> +  end if POSIX_MQ.class.method_defined?(:for_fd) && POSIX_MQ.method_defined(:to_io)

I'm not sure how you managed to run your new test at all,
I think the following is needed:

--- a/test/test_posix_mq.rb
+++ b/test/test_posix_mq.rb
@@ -17,7 +17,7 @@ class Test_POSIX_MQ < Test::Unit::TestCase
     warn "POSIX_MQ#to_io not supported on this platform: #{RUBY_PLATFORM}"
   POSIX_MQ.method_defined?(:notify) or
     warn "POSIX_MQ#notify not supported on this platform: #{RUBY_PLATFORM}"
-  POSIX_MQ.class.method_defined?(:for_fd) or
+  POSIX_MQ.respond_to?(:for_fd) or
     warn "POSIX_MQ::for_fd not supported on this platform: #{RUBY_PLATFORM}"
 
   def setup
@@ -247,7 +247,8 @@ class Test_POSIX_MQ < Test::Unit::TestCase
   end if POSIX_MQ.method_defined?(:to_io)
 
   def test_for_fd
-    @mq = POSIX_MQ.new @path, IO::CREAT|IO_RDWR, 0666
+    buf = ""
+    @mq = POSIX_MQ.new @path, IO::CREAT|IO::RDWR, 0666
     @alt = POSIX_MQ.for_fd(@mq.to_io.to_i)
     assert_equal true, @mq.send("hello", 0)
     assert_equal [ "hello", 0 ], @alt.receive(buf)
@@ -255,7 +256,7 @@ class Test_POSIX_MQ < Test::Unit::TestCase
     assert_equal @mq.to_io.to_i, @alt.to_io.to_i
     assert_raises(ArgumentError) { @alt.name }
     assert_raises(ArgumentError) { POSIX_MQ.for_fd(1) }
-  end if POSIX_MQ.class.method_defined?(:for_fd) && POSIX_MQ.method_defined(:to_io)
+  end if POSIX_MQ.respond_to?(:for_fd) && POSIX_MQ.method_defined?(:to_io)
 
   def test_notify
     rd, wr = IO.pipe

Also, I think we'll also need to support equivalents of IO#autoclose?
and IO#autoclose=, because having two POSIX_MQ objects refer to the same
FD will cause problems with the GC performing auto-close by default.


Finally, this is probably one of the last threads on this mailing list.
Librelist couldn't support rsync-able archives any longer and I'm no
longer a fan of subscription-required lists, so I'll migrate this list
to mlmmj + public-inbox.org infrastructure next week.  The only change
will be open-to-all posting without subscriptions, so Cc:-ing everyone
is required.  public-inbox/ssoma allows cloning mail archives via git.


^ permalink raw reply	[relevance 5%]

* [PATCH] Ability to adopt file descriptors
@ 2015-01-03 17:15  3% Christopher Lord
  2015-01-04  1:16  5% ` Eric Wong
  0 siblings, 1 reply; 5+ results
From: Christopher Lord @ 2015-01-03 17:15 UTC (permalink / raw)
  To: ruby.posix.mq

This patch adds support for adopting an existing file descriptor, together
with testcases. The need for this comes up when we use systemd with the
ListenMessageQueue directive. For socket activation, systemd opens the POSIX
message queue and expects user code to begin using the file descriptor
without opening it in-process.

To support the systemd model in the `posix_mq` gem, this patch suggests
imitating the behavior on the Socket class, which uses `#for_fd` to create a
socket class from a descriptor.

One confounding factor exists. POSIX queues have a name but it is difficult
to get access to this name in a safe manner from the file descriptor. One
option would be to `readlink(2)` on `/proc/self/fd/N` to get the name[1], but
note that if the descriptor is unlinked we wouldn't get anything usable.
Rather than risk incorrect behavior and extra complexity, I've decided to
just raise an `ArgumentError` if `#name` is called on adopted descriptors.
Typically one wouldn't need the actual name in a systemd socket-activated
situation, anyway.

[1]: http://stackoverflow.com/questions/1188757/getting-filename-from-file-descriptor-in-c
---
 ext/posix_mq/posix_mq.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++-
 test/test_posix_mq.rb   | 13 ++++++++++
 2 files changed, 75 insertions(+), 1 deletion(-)

diff --git a/ext/posix_mq/posix_mq.c b/ext/posix_mq/posix_mq.c
index cbc32b9..901b6ce 100644
--- a/ext/posix_mq/posix_mq.c
+++ b/ext/posix_mq/posix_mq.c
@@ -26,6 +26,7 @@
 
 #if defined(__linux__)
 #  define MQD_TO_FD(mqd) (int)(mqd)
+#  define FD_TO_MQD(fd) (mqd_t)(fd)
 #elif defined(HAVE___MQ_OSHANDLE) /* FreeBSD */
 #  define MQD_TO_FD(mqd) __mq_oshandle(mqd)
 #else
@@ -66,7 +67,7 @@ static int MQ_IO_CLOSE(struct posix_mq *mq)
 # define PMQ_TRY       (1<<1)
 
 static VALUE cAttr;
-static ID id_new, id_kill, id_fileno, id_divmod;
+static ID id_new, id_kill, id_fileno, id_divmod, id_to_i;
 static ID id_flags, id_maxmsg, id_msgsize, id_curmsgs;
 static VALUE sym_r, sym_w, sym_rw;
 static const mqd_t MQD_INVALID = (mqd_t)-1;
@@ -365,6 +366,51 @@ static void rstruct2mqattr(struct mq_attr *attr, VALUE astruct, int all)
 		attr->mq_curmsgs = NUM2LONG(tmp);
 }
 
+#ifdef FD_TO_MQD
+
+/*
+ * call-seq:
+ *	POSIX_MQ.for_fd(socket)	=> mq
+ *
+ * Adopts a socket as a POSIX message queue. Argument will be
+ * checked to ensure it is a POSIX message queue socket.
+ *
+ * This is useful for adopting systemd sockets passed via the
+ * ListenMessageQueue directive.
+ * Returns a +POSIX_MQ+ instance.  This method is only available
+ * under Linux and FreeBSD and is not intended to be portable.
+ *
+ */
+static VALUE for_fd(VALUE klass, VALUE socket)
+{
+	VALUE mqv = alloc(klass);
+	struct posix_mq *mq = get(mqv, 0);
+
+	mq->name = Qnil;
+
+	if (rb_respond_to(socket, id_to_i)) {
+		VALUE fd_num = rb_funcall(socket, id_to_i, 0);
+		mq->des = FD_TO_MQD(NUM2INT(fd_num));
+	}
+	else {
+		rb_raise(rb_eArgError, "provided argument must be (or convertable to) an integer file descriptor");
+	}
+
+	if (mq->des < 0) {
+		rb_raise(rb_eArgError, "provided argument must be a valid file descriptor");
+	}
+
+	if (mq_getattr(mq->des, &mq->attr) < 0) {
+		if (errno) {
+			rb_raise(rb_eArgError, "provided file descriptor is not a POSIX message queue");
+		}
+	}
+	return mqv;
+}
+
+
+#endif
+
 /*
  * call-seq:
  *	POSIX_MQ.new(name [, flags [, mode [, mq_attr]])	=> mq
@@ -507,6 +553,10 @@ static VALUE _unlink(VALUE self)
 	struct posix_mq *mq = get(self, 0);
 	int rv;
 
+	if (NIL_P(mq->name)) {
+		rb_raise(rb_eArgError, "can not unlink an adopted socket");
+	}
+
 	assert(TYPE(mq->name) == T_STRING && "mq->name is not a string");
 
 	rv = mq_unlink(RSTRING_PTR(mq->name));
@@ -807,6 +857,12 @@ static VALUE name(VALUE self)
 {
 	struct posix_mq *mq = get(self, 0);
 
+	if (NIL_P(mq->name)) {
+		/* We could use readlink(2) on /proc/self/fd/N, but lots of care required.
+		 * http://stackoverflow.com/questions/1188757/getting-filename-from-file-descriptor-in-c  */
+		rb_raise(rb_eArgError, "can not get name of an adopted socket");
+	}
+
 	return rb_str_dup(mq->name);
 }
 
@@ -1114,6 +1170,10 @@ void Init_posix_mq_ext(void)
 	rb_define_method(cPOSIX_MQ, "to_io", to_io, 0);
 #endif
 
+#ifdef FD_TO_MQD
+	rb_define_module_function(cPOSIX_MQ, "for_fd", for_fd, 1);
+#endif
+
 	id_new = rb_intern("new");
 	id_kill = rb_intern("kill");
 	id_fileno = rb_intern("fileno");
@@ -1122,6 +1182,7 @@ void Init_posix_mq_ext(void)
 	id_maxmsg = rb_intern("maxmsg");
 	id_msgsize = rb_intern("msgsize");
 	id_curmsgs = rb_intern("curmsgs");
+	id_to_i = rb_intern("to_i");
 	sym_r = ID2SYM(rb_intern("r"));
 	sym_w = ID2SYM(rb_intern("w"));
 	sym_rw = ID2SYM(rb_intern("rw"));
diff --git a/test/test_posix_mq.rb b/test/test_posix_mq.rb
index 1cc24aa..ceb9f7c 100644
--- a/test/test_posix_mq.rb
+++ b/test/test_posix_mq.rb
@@ -17,6 +17,8 @@ class Test_POSIX_MQ < Test::Unit::TestCase
     warn "POSIX_MQ#to_io not supported on this platform: #{RUBY_PLATFORM}"
   POSIX_MQ.method_defined?(:notify) or
     warn "POSIX_MQ#notify not supported on this platform: #{RUBY_PLATFORM}"
+  POSIX_MQ.class.method_defined?(:for_fd) or
+    warn "POSIX_MQ::for_fd not supported on this platform: #{RUBY_PLATFORM}"
 
   def setup
     @mq = nil
@@ -244,6 +246,17 @@ class Test_POSIX_MQ < Test::Unit::TestCase
     assert_nothing_raised { IO.select([@mq], nil, nil, 0) }
   end if POSIX_MQ.method_defined?(:to_io)
 
+  def test_for_fd
+    @mq = POSIX_MQ.new @path, IO::CREAT|IO_RDWR, 0666
+    @alt = POSIX_MQ.for_fd(@mq.to_io.to_i)
+    assert_equal true, @mq.send("hello", 0)
+    assert_equal [ "hello", 0 ], @alt.receive(buf)
+    assert_equal "hello", buf
+    assert_equal @mq.to_io.to_i, @alt.to_io.to_i
+    assert_raises(ArgumentError) { @alt.name }
+    assert_raises(ArgumentError) { POSIX_MQ.for_fd(1) }
+  end if POSIX_MQ.class.method_defined?(:for_fd) && POSIX_MQ.method_defined(:to_io)
+
   def test_notify
     rd, wr = IO.pipe
     orig = trap(:USR1) { wr.syswrite('.') }
-- 
1.8.3.1



^ permalink raw reply related	[relevance 3%]

Results 1-5 of 5 | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
2015-01-03 17:15  3% [PATCH] Ability to adopt file descriptors Christopher Lord
2015-01-04  1:16  5% ` Eric Wong
2015-01-04  3:34  5%   ` Christopher Lord
2015-01-05  5:34  7%     ` Eric Wong
2015-01-16 20:32  4% [ANN] posix_mq 2.2.0 - POSIX Message Queues for Ruby Eric Wong

Code repositories for project(s) associated with this public inbox

	https://yhbt.net/ruby_posix_mq.git/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).