From c8c2c3c7899022239b8e69bd4c9c1471a5d074dc Mon Sep 17 00:00:00 2001
From: Eric Wong <normalperson@yhbt.net>
Date: Fri, 25 Mar 2011 10:46:26 -0700
Subject: [PATCH] IO#close releases GVL if possible

close() may block for certain file types (NFS, SO_LINGER
sockets, inotify), so let other threads run.
---
 io.c |   21 +++++++++++++++++++--
 1 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/io.c b/io.c
index 064d1a2..57bfa42 100644
--- a/io.c
+++ b/io.c
@@ -3489,6 +3489,23 @@ finish_writeconv_sync(VALUE arg)
     return finish_writeconv(p->fptr, p->noalloc);
 }
 
+static VALUE
+nogvl_close(void *ptr)
+{
+    int *fd = (int *)ptr;
+
+    return (VALUE)close(*fd);
+}
+
+static int
+maygvl_close(int fd, int keepgvl)
+{
+    if (keepgvl)
+	return close(fd);
+
+    return (int)rb_thread_blocking_region(nogvl_close, &fd, RUBY_UBF_IO, 0);
+}
+
 static void
 fptr_finalize(rb_io_t *fptr, int noraise)
 {
@@ -3527,7 +3544,7 @@ fptr_finalize(rb_io_t *fptr, int noraise)
         /* fptr->fd may be closed even if close fails.
          * POSIX doesn't specify it.
          * We assumes it is closed.  */
-        if (close(fptr->fd) < 0 && NIL_P(err))
+        if (maygvl_close(fptr->fd, noraise) < 0 && NIL_P(err))
             err = noraise ? Qtrue : INT2NUM(errno);
     }
   skip_fd_close:
@@ -5890,7 +5907,7 @@ rb_io_reopen(int argc, VALUE *argv, VALUE file)
 #endif
     }
     else {
-        if (close(fptr->fd) < 0)
+        if (maygvl_close(fptr->fd, 0) < 0)
             rb_sys_fail_path(fptr->pathv);
         fptr->fd = -1;
         fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
-- 
1.7.4.1.416.ged9c5

