about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2011-02-22 16:46:26 -0800
committerEric Wong <normalperson@yhbt.net>2011-02-22 16:46:26 -0800
commit3a8a20d685dbfb500187099d76e56e848ad347ed (patch)
treee70d7bca1b7b60f8dfb731971fb92d65d09af42c
parentc4c4554c3ceef9208fe7f8473b970e9f522ab9b9 (diff)
downloadruby_posix_mq-3a8a20d685dbfb500187099d76e56e848ad347ed.tar.gz
Some ancient systems don't support mq_timedsend and
mq_timedreceive but somehow manage to support other POSIX
mq_* functions.
-rw-r--r--ext/posix_mq/extconf.rb3
-rw-r--r--ext/posix_mq/posix_mq.c31
-rw-r--r--test/test_posix_mq.rb27
3 files changed, 56 insertions, 5 deletions
diff --git a/ext/posix_mq/extconf.rb b/ext/posix_mq/extconf.rb
index ed119a3..310de3d 100644
--- a/ext/posix_mq/extconf.rb
+++ b/ext/posix_mq/extconf.rb
@@ -10,4 +10,7 @@ have_func('rb_thread_blocking_region')
 have_library("m")
 have_library("rt")
 have_library("pthread")
+
+have_func("mq_timedsend")
+have_func("mq_timedreceive")
 create_makefile("posix_mq_ext")
diff --git a/ext/posix_mq/posix_mq.c b/ext/posix_mq/posix_mq.c
index 01b5dbd..d59cd30 100644
--- a/ext/posix_mq/posix_mq.c
+++ b/ext/posix_mq/posix_mq.c
@@ -133,6 +133,30 @@ struct rw_args {
         struct timespec *timeout;
 };
 
+#ifndef HAVE_MQ_TIMEDSEND
+static mqd_t
+not_timedsend(mqd_t mqdes, const char *msg_ptr,
+              size_t msg_len, unsigned msg_prio,
+              const struct timespec *abs_timeout)
+{
+        rb_bug("mq_timedsend workaround failed");
+        return (mqd_t)-1;
+}
+#  define mq_timedsend not_timedsend
+#endif
+#ifndef HAVE_MQ_TIMEDRECEIVE
+static ssize_t
+not_timedreceive(mqd_t mqdes, char *msg_ptr,
+                 size_t msg_len, unsigned *msg_prio,
+                 const struct timespec *abs_timeout)
+{
+        rb_bug("mq_timedreceive workaround failed");
+        return (mqd_t)-1;
+}
+#  define mq_timedreceive not_timedreceive
+#endif
+
+#if defined(HAVE_MQ_TIMEDRECEIVE) && defined(HAVE_MQ_TIMEDSEND)
 static void num2timespec(struct timespec *ts, VALUE t)
 {
         switch (TYPE(t)) {
@@ -174,6 +198,13 @@ static void num2timespec(struct timespec *ts, VALUE t)
                 }
         }
 }
+#else
+static void num2timespec(struct timespec *ts, VALUE t)
+{
+        rb_raise(rb_eNotImpError,
+                 "mq_timedsend and/or mq_timedreceive missing");
+}
+#endif
 
 static struct timespec *convert_timeout(struct timespec *dest, VALUE t)
 {
diff --git a/test/test_posix_mq.rb b/test/test_posix_mq.rb
index f7dec3c..8febb04 100644
--- a/test/test_posix_mq.rb
+++ b/test/test_posix_mq.rb
@@ -62,7 +62,7 @@ class Test_POSIX_MQ < Test::Unit::TestCase
     @mq = POSIX_MQ.new(@path, :rw)
     assert ! @mq.nonblock?
     t0 = Time.now
-    assert_raises(Errno::ETIMEDOUT) { @mq.receive "", interval }
+    maybe_timeout { @mq.receive "", interval } or return
     elapsed = Time.now - t0
     assert elapsed > interval, elapsed.inspect
     assert elapsed < 0.02, elapsed.inspect
@@ -76,7 +76,7 @@ class Test_POSIX_MQ < Test::Unit::TestCase
     @mq = POSIX_MQ.new(@path, :rw)
     assert ! @mq.nonblock?
     t0 = Time.now
-    assert_raises(Errno::ETIMEDOUT) { @mq.receive "", interval }
+    maybe_timeout { @mq.receive "", interval } or return
     elapsed = Time.now - t0
     assert elapsed >= 0.01, elapsed.inspect
     assert elapsed <= 0.02, elapsed.inspect
@@ -87,7 +87,7 @@ class Test_POSIX_MQ < Test::Unit::TestCase
     @mq = POSIX_MQ.new(@path, :rw)
     assert ! @mq.nonblock?
     t0 = Time.now
-    assert_raises(Errno::ETIMEDOUT) { @mq.receive "", interval }
+    maybe_timeout { @mq.receive "", interval } or return
     elapsed = Time.now - t0
     assert elapsed >= interval, elapsed.inspect
     assert elapsed < 1.10, elapsed.inspect
@@ -97,9 +97,15 @@ class Test_POSIX_MQ < Test::Unit::TestCase
     interval = 0.01
     @mq = POSIX_MQ.new(@path, :rw, 0666, POSIX_MQ::Attr[0, 1, 1, 0])
     assert ! @mq.nonblock?
-    assert_nothing_raised { @mq.send "A", 1, interval }
+    assert_nothing_raised {
+      begin
+        @mq.send "A", 1, interval
+      rescue NotImplementedError
+        return
+      end
+    }
     t0 = Time.now
-    assert_raises(Errno::ETIMEDOUT) { @mq.send "B", 1, interval }
+    maybe_timeout { @mq.send "B", 1, interval } or return
     elapsed = Time.now - t0
     assert elapsed > interval
   end
@@ -344,4 +350,15 @@ class Test_POSIX_MQ < Test::Unit::TestCase
     assert_raises(TypeError) { @mq.attr = {} }
     assert_raises(TypeError) { @mq.attr = Struct.new(:a,:b,:c,:d).new }
   end
+
+  def maybe_timeout
+    yield
+    assert_raises(exc) { } # FAIL
+    return true
+    rescue Errno::ETIMEDOUT => e
+      return true
+    rescue NotImplementedError => e
+      warn "E: #{e}"
+      return false
+  end
 end