about summary refs log tree commit homepage
path: root/ext/posix_mq/posix_mq.c
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2010-08-02 08:28:15 +0000
committerEric Wong <normalperson@yhbt.net>2010-08-02 08:31:37 +0000
commit3cf7ec34b6319693af14215ebb0da51c3e6a4603 (patch)
tree0a945e53ec5a4b7d566260363b0e7d1fd166e13b /ext/posix_mq/posix_mq.c
parent3ca83d322486bb3da20d974af7faa74f9df891d8 (diff)
downloadruby_posix_mq-3cf7ec34b6319693af14215ebb0da51c3e6a4603.tar.gz
On ENOMEM, EMFILE, and ENFILE errors, it is customary to
invoke the Ruby GC and free up resources and retry the
system call.
Diffstat (limited to 'ext/posix_mq/posix_mq.c')
-rw-r--r--ext/posix_mq/posix_mq.c30
1 files changed, 24 insertions, 6 deletions
diff --git a/ext/posix_mq/posix_mq.c b/ext/posix_mq/posix_mq.c
index db50534..04c1ea0 100644
--- a/ext/posix_mq/posix_mq.c
+++ b/ext/posix_mq/posix_mq.c
@@ -362,8 +362,14 @@ static VALUE init(int argc, VALUE *argv, VALUE self)
         }
 
         mq->des = (mqd_t)xopen(&x);
-        if (mq->des == MQD_INVALID)
-                rb_sys_fail("mq_open");
+        if (mq->des == MQD_INVALID) {
+                if (errno == ENOMEM || errno == EMFILE || errno == ENFILE) {
+                        rb_gc();
+                        mq->des = (mqd_t)xopen(&x);
+                }
+                if (mq->des == MQD_INVALID)
+                        rb_sys_fail("mq_open");
+        }
 
         mq->name = rb_str_dup(name);
         if (x.oflags & O_NONBLOCK)
@@ -736,6 +742,20 @@ static void thread_notify_fd(union sigval sv)
         while ((write(fd, "", 1) < 0) && (errno == EINTR || errno == EAGAIN));
 }
 
+static void my_mq_notify(mqd_t des, struct sigevent *not)
+{
+        mqd_t rv = mq_notify(des, not);
+
+        if (rv == MQD_INVALID) {
+                if (errno == ENOMEM) {
+                        rb_gc();
+                        rv = mq_notify(des, not);
+                }
+                if (rv == MQD_INVALID)
+                        rb_sys_fail("mq_notify");
+        }
+}
+
 /* :nodoc: */
 static VALUE setnotify_exec(VALUE self, VALUE io, VALUE thr)
 {
@@ -763,8 +783,7 @@ static VALUE setnotify_exec(VALUE self, VALUE io, VALUE thr)
                 rb_funcall(mq->thread, id_kill, 0, 0);
         mq->thread = thr;
 
-        if (mq_notify(mq->des, &not) < 0)
-                rb_sys_fail("mq_notify");
+        my_mq_notify(mq->des, &not);
 
         return thr;
 }
@@ -834,8 +853,7 @@ static VALUE setnotify(VALUE self, VALUE arg)
                 rb_raise(rb_eArgError, "must be a signal or nil");
         }
 
-        if (mq_notify(mq->des, notification) < 0)
-                rb_sys_fail("mq_notify");
+        my_mq_notify(mq->des, notification);
 
         return rv;
 }