diff options
author | Christopher Lord <christopher@lord.ac> | 2015-01-03 10:15:58 -0700 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2015-01-04 23:51:17 +0000 |
commit | 6622d115c795d88b99d844ce8b74e979a2b55ae6 (patch) | |
tree | 291420e6af7d4b7576b8638539ee278e96c7aad7 /test/test_posix_mq.rb | |
parent | b14ae708a9e53b1f8a274aa78a610b2f776847f5 (diff) | |
download | ruby_posix_mq-6622d115c795d88b99d844ce8b74e979a2b55ae6.tar.gz |
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 [ew: simplified type checks to be consistent with IO.for_fd, fixed test case] Signed-off-by: Eric Wong <normalperson@yhbt.net>
Diffstat (limited to 'test/test_posix_mq.rb')
-rw-r--r-- | test/test_posix_mq.rb | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/test/test_posix_mq.rb b/test/test_posix_mq.rb index 1cc24aa..54c7223 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.respond_to?(:for_fd) or + warn "POSIX_MQ::for_fd not supported on this platform: #{RUBY_PLATFORM}" def setup @mq = nil @@ -244,6 +246,18 @@ 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 + 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) + assert_equal "hello", buf + assert_equal @mq.to_io.to_i, @alt.to_io.to_i + assert_raises(ArgumentError) { @alt.name } + assert_raises(Errno::EBADF) { POSIX_MQ.for_fd(1) } + end if POSIX_MQ.respond_to?(:for_fd) && POSIX_MQ.method_defined?(:to_io) + def test_notify rd, wr = IO.pipe orig = trap(:USR1) { wr.syswrite('.') } |