[#34647] fork 不可能な環境での test_argv0_noarg — wanabe <s.wanabe@...>

ワナベと申します。

13 messages 2008/05/11
[#34667] Re: fork 不可能な環境での test_argv0_noarg — Yukihiro Matsumoto <matz@...> 2008/05/13

まつもと ゆきひろです

[#34742] Ruby 1.8.7-preview3 has been released — "Akinori MUSHA" <knu@...>

 Ruby 1.8.7-preview3 をリリースしました。

14 messages 2008/05/18
[#34744] Re: [ruby-list:44957] Ruby 1.8.7-preview3 has been released — Takahiro Kambe <taca@...> 2008/05/19

お疲れ様です。

[#34800] Windows2000上でtrunkがビルドできない — KIMURA Koichi <kimura.koichi@...>

木村です。

18 messages 2008/05/22
[#34801] Re: Windows2000上でtrunkがビルドできない — "U.Nakamura" <usa@...> 2008/05/22

こんにちは、なかむら(う)です。

[#34824] Re: Windows2000上でtrunkがビルドできない — KIMURA Koichi <kimura.koichi@...> 2008/05/23

木村です。

[#34850] Re: Windows2000上でtrunkがビルドできない — KIMURA Koichi <kimura.koichi@...> 2008/05/26

木村です。

[#34854] Re: Windows2000上でtrunkがビルドできない — "U.Nakamura" <usa@...> 2008/05/26

こんにちは、なかむら(う)です。

[#34889] Ruby 1.8.7-preview4 test-all failed in OpenSSL::TestSSL — Nobuhiro IMAI <nov@...>

いまいです。

10 messages 2008/05/29

[ruby-dev:34572] Re: write to broken pipe on Linux

From: Nobuyoshi Nakada <nobu@...>
Date: 2008-05-02 05:57:23 UTC
List: ruby-dev #34572
なかだです。

At Fri, 2 May 2008 04:35:52 +0900,
Yukihiro Matsumoto wrote in [ruby-dev:34568]:
> |http://rryu.sakura.ne.jp/nisenise-fuhito/2008/04/22/950.html と
> |か(見落としてましたが)[ruby-list:43356]にある、接続が切れたソケッ
> |トに書き込もうとすると、二度目以降selectの待ち状態から抜けなくな
> |る問題のパッチです。rb_io_wait_{read,writ}able()の互換性がなくなっ
> |てしまうのが気になるので、名前を変えたほうがいいかもしれませんが、
> |どういうのがいいですかねぇ。
> 
> 名前も気になるのですが、この現象がlinux特有のものかどうかも気
> になります。いっそ、EPIPEを受けたらcloseとかshutdownとか呼ん
> じゃえばいいんじゃないですかね。それだとlinux固有かどうか考え
> なくてもいいし、引数変えなくていいし。

上記リンク先の情報によると、少なくともWindows VistaとMac OS X
10.5では発生しないようです。

shutdownでは、EPIPEの代わりにENOTCONNが発生するようになるだけで
その次の書き込みでやはりブロックしてしまうようです。closeにする
とEBADFにはなるのですが、eof?やcloseでも同じくEBADFが発生してし
まうようになります。他のスレッドの有無によって動作が変わってしま
うのもどうかという気もしますが。

というか、1.9ではすでにblocking regionを使えばselectは必要ないは
ずです。


Index: io.c
===================================================================
--- io.c	(revision 16261)
+++ io.c	(working copy)
@@ -187,5 +187,4 @@ static int max_file_descriptor = NOFILE;
 #define READ_CHECK(fptr) do {\
     if (!READ_DATA_PENDING(fptr)) {\
-	rb_thread_wait_fd((fptr)->fd);\
 	rb_io_check_closed(fptr);\
      }\
@@ -513,18 +512,19 @@ struct io_internal_struct {
     void *buf;
     size_t capa;
-    int is_read;
 };
 
 static VALUE
-internal_io_func(void *ptr)
+internal_read_func(void *ptr)
 {
     struct io_internal_struct *iis = (struct io_internal_struct*)ptr;
-    if (iis->is_read) {
 	return read(iis->fd, iis->buf, iis->capa);
     }
-    else {
+
+static VALUE
+internal_write_func(void *ptr)
+{
+    struct io_internal_struct *iis = (struct io_internal_struct*)ptr;
 	return write(iis->fd, iis->buf, iis->capa);
     }
-}
 
 static int
@@ -535,7 +535,6 @@ rb_read_internal(int fd, void *buf, size
     iis.buf = buf;
     iis.capa = count;
-    iis.is_read = 1;
 
-    return rb_thread_blocking_region(internal_io_func, &iis, RB_UBF_DFL, 0);
+    return rb_thread_blocking_region(internal_read_func, &iis, RB_UBF_DFL, 0);
 }
 
@@ -547,7 +546,6 @@ rb_write_internal(int fd, void *buf, siz
     iis.buf = buf;
     iis.capa = count;
-    iis.is_read = 0;
 
-    return rb_thread_blocking_region(internal_io_func, &iis, RB_UBF_DFL, 0);
+    return rb_thread_blocking_region(internal_write_func, &iis, RB_UBF_DFL, 0);
 }
 
@@ -617,5 +615,4 @@ rb_io_wait_readable(int f)
       case ERESTART:
 #endif
-	rb_thread_wait_fd(f);
 	return Qtrue;
 
@@ -659,5 +656,4 @@ rb_io_wait_writable(int f)
       case ERESTART:
 #endif
-	rb_thread_fd_writable(f);
 	return Qtrue;
 
@@ -731,9 +727,5 @@ io_fwrite(VALUE str, rb_io_t *fptr)
         if (n == 0)
             return len;
-        /* avoid context switch between "a" and "\n" in STDERR.puts "a".
-           [ruby-dev:25080] */
-	if (fptr->stdio_file != stderr && !rb_thread_fd_writable(fptr->fd)) {
 	    rb_io_check_closed(fptr);
-	}
       retry:
         l = n;
@@ -1303,5 +1295,4 @@ io_fread(VALUE str, long offset, rb_io_t
 	    if ((n -= c) <= 0) break;
 	}
-	rb_thread_wait_fd(fptr->fd);
 	rb_io_check_closed(fptr);
 	if (io_fillbuf(fptr) < 0) {
@@ -1474,9 +1465,6 @@ io_getpartial(int argc, VALUE *argv, VAL
         if (nonblock) {
             rb_io_set_nonblock(fptr);
-	    n = rb_read_internal(fptr->fd, RSTRING_PTR(str), len);
         }
-        else {
             n = rb_read_internal(fptr->fd, RSTRING_PTR(str), len);
-	}
         if (n < 0) {
             if (!nonblock && rb_io_wait_readable(fptr->fd))
@@ -1776,5 +1764,4 @@ appendline(rb_io_t *fptr, int delim, VAL
 	    }
 	}
-	rb_thread_wait_fd(fptr->fd);
 	rb_io_check_closed(fptr);
 	if (io_fillbuf(fptr) < 0) {
@@ -1813,5 +1800,4 @@ swallow(rb_io_t *fptr, int term)
 		rb_sys_fail(fptr->path);
 	}
-	rb_thread_wait_fd(fptr->fd);
 	rb_io_check_closed(fptr);
     } while (io_fillbuf(fptr) == 0);
@@ -1853,5 +1839,4 @@ rb_io_getline_fast(rb_io_t *fptr)
 	    if (e) break;
 	}
-	rb_thread_wait_fd(fptr->fd);
 	rb_io_check_closed(fptr);
 	if (io_fillbuf(fptr) < 0) {
@@ -2419,17 +2404,9 @@ rb_io_getc(VALUE io)
     return io_getc(fptr, enc);
 }
+
 int
 rb_getc(FILE *f)
 {
-    int c;
-
-    if (!STDIO_READ_DATA_PENDING(f)) {
-	rb_thread_wait_fd(fileno(f));
-    }
-    TRAP_BEG;
-    c = getc(f);
-    TRAP_END;
-
-    return c;
+    return rb_thread_blocking_region((rb_blocking_function_t*)fgetc, f, RB_UBF_DFL, 0);
 }
 
@@ -3024,10 +3001,6 @@ rb_io_syswrite(VALUE io, VALUE str)
 	rb_warn("syswrite for buffered IO");
     }
-    if (!rb_thread_fd_writable(fptr->fd)) {
         rb_io_check_closed(fptr);
-    }
-    TRAP_BEG;
-    n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
-    TRAP_END;
+    n = rb_write_internal(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
 
     if (n == -1) rb_sys_fail(fptr->path);
@@ -3080,5 +3053,4 @@ rb_io_sysread(int argc, VALUE *argv, VAL
 
     n = fptr->fd;
-    rb_thread_wait_fd(fptr->fd);
     rb_io_check_closed(fptr);
     if (RSTRING_LEN(str) != ilen) {
@@ -6632,5 +6604,4 @@ copy_stream_fallback_body(VALUE arg)
         else {
             ssize_t ss;
-            rb_thread_wait_fd(stp->src_fd);
             rb_str_resize(buf, buflen);
             ss = copy_stream_read(stp, RSTRING_PTR(buf), l, off);
Index: ext/socket/socket.c
===================================================================
--- ext/socket/socket.c	(revision 16261)
+++ ext/socket/socket.c	(working copy)
@@ -103,4 +103,6 @@ int Rconnect();
 #endif
 
+#define BLOCKING_REGION(func, arg) (long)rb_thread_blocking_region((func), (arg), RB_UBF_DFL, 0)
+
 #define INET_CLIENT 0
 #define INET_SERVER 1
@@ -496,35 +498,58 @@ bsock_getpeername(VALUE sock)
 }
 
+struct send_arg {
+    int fd, flags;
+    VALUE mesg;
+    struct sockaddr *to;
+    socklen_t tolen;
+};
+
+static VALUE
+sendto_blocking(void *data)
+{
+    struct send_arg *arg = data;
+    VALUE mesg = arg->mesg;
+    return (VALUE)sendto(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg),
+			 arg->flags, arg->to, arg->tolen);
+}
+
+static VALUE
+send_blocking(void *data)
+{
+    struct send_arg *arg = data;
+    VALUE mesg = arg->mesg;
+    return (VALUE)send(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg),
+		       arg->flags);
+}
+
 static VALUE
 bsock_send(int argc, VALUE *argv, VALUE sock)
 {
-    VALUE mesg, to;
-    VALUE flags;
+    struct send_arg arg;
+    VALUE flags, to;
     rb_io_t *fptr;
-    int fd, n;
+    int n;
+    rb_blocking_function_t *func;
 
     rb_secure(4);
-    rb_scan_args(argc, argv, "21", &mesg, &flags, &to);
+    rb_scan_args(argc, argv, "21", &arg.mesg, &flags, &to);
 
-    StringValue(mesg);
-    if (!NIL_P(to)) StringValue(to);
-    GetOpenFile(sock, fptr);
-    fd = fptr->fd;
-    rb_thread_fd_writable(fd);
-  retry:
+    StringValue(arg.mesg);
     if (!NIL_P(to)) {
-        TRAP_BEG;
-	n = sendto(fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg), NUM2INT(flags),
-		   (struct sockaddr*)RSTRING_PTR(to), RSTRING_LEN(to));
-        TRAP_END;
+	StringValue(to);
+	to = rb_str_new4(to);
+	arg.to = (struct sockaddr *)RSTRING_PTR(to);
+	arg.tolen = RSTRING_LEN(to);
+	func = sendto_blocking;
     }
     else {
-        TRAP_BEG;
-	n = send(fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg), NUM2INT(flags));
-        TRAP_END;
+	func = send_blocking;
     }
-    if (n < 0) {
-	if (rb_io_wait_writable(fd)) {
-	    goto retry;
+    GetOpenFile(sock, fptr);
+    arg.fd = fptr->fd;
+    arg.flags = NUM2INT(flags);
+    while ((n = (int)BLOCKING_REGION(func, &arg)) < 0) {
+	if (rb_io_wait_writable(arg.fd)) {
+	    continue;
 	}
 	rb_sys_fail("send(2)");
@@ -570,20 +595,33 @@ enum sock_recv_type {
 };
 
+struct recvfrom_arg {
+    int fd, flags;
+    VALUE str;
+    socklen_t alen;
+    char buf[1024];
+};
+
+static VALUE
+recvfrom_blocking(void *data)
+{
+    struct recvfrom_arg *arg = data;
+    return (VALUE)recvfrom(arg->fd, RSTRING_PTR(arg->str), RSTRING_LEN(arg->str),
+			   arg->flags, (struct sockaddr*)arg->buf, &arg->alen);
+}
+
 static VALUE
 s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from)
 {
     rb_io_t *fptr;
-    VALUE str;
-    char buf[1024];
-    socklen_t alen = sizeof buf;
+    VALUE str, klass;
+    struct recvfrom_arg arg;
     VALUE len, flg;
     long buflen;
     long slen;
-    int fd, flags;
 
     rb_scan_args(argc, argv, "11", &len, &flg);
 
-    if (flg == Qnil) flags = 0;
-    else             flags = NUM2INT(flg);
+    if (flg == Qnil) arg.flags = 0;
+    else             arg.flags = NUM2INT(flg);
     buflen = NUM2INT(len);
 
@@ -592,24 +630,19 @@ s_recvfrom(VALUE sock, int argc, VALUE *
 	rb_raise(rb_eIOError, "recv for buffered IO");
     }
-    fd = fptr->fd;
-
-    str = rb_tainted_str_new(0, buflen);
+    arg.fd = fptr->fd;
+    arg.alen = sizeof(arg.buf);
 
-  retry:
-    rb_thread_wait_fd(fd);
-    rb_io_check_closed(fptr);
-    if (RSTRING_LEN(str) != buflen) {
+    arg.str = str = rb_tainted_str_new(0, buflen);
+    klass = RBASIC(str)->klass;
+    RBASIC(str)->klass = 0;
+
+    while (rb_io_check_closed(fptr),
+	   (slen = BLOCKING_REGION(recvfrom_blocking, &arg)) < 0) {
+	if (RBASIC(str)->klass || RSTRING_LEN(str) != buflen) {
 	rb_raise(rb_eRuntimeError, "buffer string modified");
     }
-    TRAP_BEG;
-    slen = recvfrom(fd, RSTRING_PTR(str), buflen, flags, (struct sockaddr*)buf, &alen);
-    TRAP_END;
-
-    if (slen < 0) {
-	if (rb_io_wait_readable(fd)) {
-	    goto retry;
-	}
-	rb_sys_fail("recvfrom(2)");
     }
+
+    RBASIC(str)->klass = klass;
     if (slen < RSTRING_LEN(str)) {
 	rb_str_set_len(str, slen);
@@ -618,13 +651,13 @@ s_recvfrom(VALUE sock, int argc, VALUE *
     switch (from) {
       case RECV_RECV:
-	return (VALUE)str;
+	return str;
       case RECV_IP:
 #if 0
-	if (alen != sizeof(struct sockaddr_in)) {
+	if (arg.alen != sizeof(struct sockaddr_in)) {
 	    rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
 	}
 #endif
-	if (alen && alen != sizeof(buf)) /* OSX doesn't return a from result for connection-oriented sockets */
-	    return rb_assoc_new(str, ipaddr((struct sockaddr*)buf, fptr->mode & FMODE_NOREVLOOKUP));
+	if (arg.alen && arg.alen != sizeof(arg.buf)) /* OSX doesn't return a from result for connection-oriented sockets */
+	    return rb_assoc_new(str, ipaddr((struct sockaddr*)arg.buf, fptr->mode & FMODE_NOREVLOOKUP));
 	else
 	    return rb_assoc_new(str, Qnil);
@@ -632,8 +665,8 @@ s_recvfrom(VALUE sock, int argc, VALUE *
 #ifdef HAVE_SYS_UN_H
       case RECV_UNIX:
-        return rb_assoc_new(str, unixaddr((struct sockaddr_un*)buf, alen));
+        return rb_assoc_new(str, unixaddr((struct sockaddr_un*)arg.buf, arg.alen));
 #endif
       case RECV_SOCKET:
-	return rb_assoc_new(str, rb_str_new(buf, alen));
+	return rb_assoc_new(str, rb_str_new(arg.buf, arg.alen));
       default:
 	rb_bug("s_recvfrom called with bad value");
@@ -924,5 +957,6 @@ sock_addrinfo(VALUE host, VALUE port, in
                 if (r->ai_socktype == SOCK_DGRAM) {
                     r->ai_protocol = IPPROTO_UDP;
-                } else if (r->ai_socktype == SOCK_STREAM) {
+		}
+		else if (r->ai_socktype == SOCK_STREAM) {
                     r->ai_protocol = IPPROTO_TCP;
                 }
@@ -1096,9 +1130,32 @@ wait_connectable(int fd)
 #endif
 
+struct connect_arg {
+    int fd;
+    const struct sockaddr *sockaddr;
+    socklen_t len;
+};
+
+static VALUE
+connect_blocking(void *data)
+{
+    struct connect_arg *arg = data;
+    return (VALUE)connect(arg->fd, arg->sockaddr, arg->len);
+}
+
+#if defined(SOCKS) && !defined(SOCKS5)
+static VALUE
+socks_connect_blocking(void *data)
+{
+    struct connect_arg *arg = data;
+    return (VALUE)Rconnect(arg->fd, arg->sockaddr, arg->len);
+}
+#endif
+
 static int
-ruby_connect(int fd, struct sockaddr *sockaddr, int len, int socks)
+ruby_connect(int fd, const struct sockaddr *sockaddr, int len, int socks)
 {
     int status;
-    int mode;
+    rb_blocking_function_t *func = connect_blocking;
+    struct connect_arg arg;
 #if WAIT_IN_PROGRESS > 0
     int wait_in_progress = -1;
@@ -1107,36 +1164,12 @@ ruby_connect(int fd, struct sockaddr *so
 #endif
 
-#if defined(HAVE_FCNTL)
-# if defined(F_GETFL)
-    mode = fcntl(fd, F_GETFL, 0);
-# else
-    mode = 0;
-# endif
-
-#ifdef O_NDELAY
-# define NONBLOCKING O_NDELAY
-#else
-#ifdef O_NBIO
-# define NONBLOCKING O_NBIO
-#else
-# define NONBLOCKING O_NONBLOCK
-#endif
-#endif
-#ifdef SOCKS5
-    if (!socks)
-#endif
-    fcntl(fd, F_SETFL, mode|NONBLOCKING);
-#endif /* HAVE_FCNTL */
-
-    for (;;) {
+    arg.fd = fd;
+    arg.sockaddr = sockaddr;
+    arg.len = len;
 #if defined(SOCKS) && !defined(SOCKS5)
-	if (socks) {
-	    status = Rconnect(fd, sockaddr, len);
-	}
-	else
+    if (socks) func = socks_connect_blocking;
 #endif
-	{
-	    status = connect(fd, sockaddr, len);
-	}
+    for (;;) {
+	status = (int)BLOCKING_REGION(func, &arg);
 	if (status < 0) {
 	    switch (errno) {
@@ -1199,7 +1232,4 @@ ruby_connect(int fd, struct sockaddr *so
 	    }
 	}
-#ifdef HAVE_FCNTL
-	fcntl(fd, F_SETFL, mode);
-#endif
 	return status;
     }
@@ -1240,5 +1270,5 @@ init_inetsock_internal(struct inetsock_a
     struct addrinfo *res;
     int fd, status = 0;
-    char *syscall;
+    char *syscall = 0;
 
     arg->remote.res = sock_addrinfo(arg->remote.host, arg->remote.serv, SOCK_STREAM,
@@ -1296,7 +1326,4 @@ init_inetsock_internal(struct inetsock_a
     arg->fd = -1;
 
-    if (type == INET_SERVER)
-	listen(fd, 5);
-
     /* create new instance */
     return init_sock(arg->sock, fd);
@@ -1450,10 +1477,17 @@ static VALUE
 tcp_svr_init(int argc, VALUE *argv, VALUE sock)
 {
-    VALUE arg1, arg2;
+    VALUE arg1, arg2, blog;
+    rb_io_t *fptr;
+    int backlog = 5;
 
-    if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2)
-	return init_inetsock(sock, arg1, arg2, Qnil, Qnil, INET_SERVER);
-    else
-	return init_inetsock(sock, Qnil, arg1, Qnil, Qnil, INET_SERVER);
+    if (rb_scan_args(argc, argv, "11:backlog", &arg1, &arg2, &blog) != 2)
+	arg2 = arg1, arg1 = Qnil;
+    if (!NIL_P(blog)) backlog = NUM2INT(blog);
+    sock = init_inetsock(sock, arg1, arg2, Qnil, Qnil, INET_SERVER);
+    GetOpenFile(sock, fptr);
+    if (listen(fptr->fd, backlog)) {
+	rb_sys_fail("listen");
+    }
+    return sock;
 }
 
@@ -1491,4 +1525,17 @@ s_accept_nonblock(VALUE klass, rb_io_t *
 }
 
+struct accept_arg {
+    int fd;
+    struct sockaddr *sockaddr;
+    socklen_t *len;
+};
+
+static VALUE
+accept_blocking(void *data)
+{
+    struct accept_arg *arg = data;
+    return (VALUE)accept(arg->fd, arg->sockaddr, arg->len);
+}
+
 static VALUE
 s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len)
@@ -1496,15 +1543,12 @@ s_accept(VALUE klass, int fd, struct soc
     int fd2;
     int retry = 0;
+    struct accept_arg arg;
 
     rb_secure(3);
+    arg.fd = fd;
+    arg.sockaddr = sockaddr;
+    arg.len = len;
   retry:
-    rb_thread_wait_fd(fd);
-#if defined(_nec_ews)
-    fd2 = accept(fd, sockaddr, len);
-#else
-    TRAP_BEG;
-    fd2 = accept(fd, sockaddr, len);
-    TRAP_END;
-#endif
+    fd2 = (int)BLOCKING_REGION(accept_blocking, &arg);
     if (fd2 < 0) {
 	switch (errno) {
@@ -1787,8 +1831,9 @@ static VALUE
 udp_send(int argc, VALUE *argv, VALUE sock)
 {
-    VALUE mesg, flags, host, port;
+    VALUE flags, host, port;
     rb_io_t *fptr;
     int n;
     struct addrinfo *res0, *res;
+    struct send_arg arg;
 
     if (argc == 2 || argc == 3) {
@@ -1796,13 +1841,16 @@ udp_send(int argc, VALUE *argv, VALUE so
     }
     rb_secure(4);
-    rb_scan_args(argc, argv, "4", &mesg, &flags, &host, &port);
+    rb_scan_args(argc, argv, "4", &arg.mesg, &flags, &host, &port);
 
-    StringValue(mesg);
+    StringValue(arg.mesg);
     res0 = sock_addrinfo(host, port, SOCK_DGRAM, 0);
     GetOpenFile(sock, fptr);
+    arg.fd = fptr->fd;
+    arg.flags = NUM2INT(flags);
     for (res = res0; res; res = res->ai_next) {
       retry:
-	n = sendto(fptr->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg), NUM2INT(flags),
-		   res->ai_addr, res->ai_addrlen);
+	arg.to = res->ai_addr;
+	arg.tolen = res->ai_addrlen;
+	n = (int)BLOCKING_REGION(sendto_blocking, &arg);
 	if (n >= 0) {
 	    freeaddrinfo(res0);
@@ -1920,4 +1968,16 @@ unix_recvfrom(int argc, VALUE *argv, VAL
 #endif
 
+struct iomsg_arg {
+    int fd;
+    struct msghdr msg;
+};
+
+static VALUE
+sendmsg_blocking(void *data)
+{
+    struct iomsg_arg *arg = data;
+    return sendmsg(arg->fd, &arg->msg, 0);
+}
+
 static VALUE
 unix_send_io(VALUE sock, VALUE val)
@@ -1926,5 +1986,5 @@ unix_send_io(VALUE sock, VALUE val)
     int fd;
     rb_io_t *fptr;
-    struct msghdr msg;
+    struct iomsg_arg arg;
     struct iovec vec[1];
     char buf[1];
@@ -1951,6 +2011,6 @@ unix_send_io(VALUE sock, VALUE val)
     GetOpenFile(sock, fptr);
 
-    msg.msg_name = NULL;
-    msg.msg_namelen = 0;
+    arg.msg.msg_name = NULL;
+    arg.msg.msg_namelen = 0;
 
     /* Linux and Solaris doesn't work if msg_iov is NULL. */
@@ -1958,11 +2018,11 @@ unix_send_io(VALUE sock, VALUE val)
     vec[0].iov_base = buf;
     vec[0].iov_len = 1;
-    msg.msg_iov = vec;
-    msg.msg_iovlen = 1;
+    arg.msg.msg_iov = vec;
+    arg.msg.msg_iovlen = 1;
 
 #if FD_PASSING_BY_MSG_CONTROL
-    msg.msg_control = (caddr_t)&cmsg;
-    msg.msg_controllen = CMSG_LEN(sizeof(int));
-    msg.msg_flags = 0;
+    arg.msg.msg_control = (caddr_t)&cmsg;
+    arg.msg.msg_controllen = CMSG_LEN(sizeof(int));
+    arg.msg.msg_flags = 0;
     MEMZERO((char*)&cmsg, char, sizeof(cmsg));
     cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(int));
@@ -1971,9 +2031,10 @@ unix_send_io(VALUE sock, VALUE val)
     *(int *)CMSG_DATA(&cmsg.hdr) = fd;
 #else
-    msg.msg_accrights = (caddr_t)&fd;
-    msg.msg_accrightslen = sizeof(fd);
+    arg.msg.msg_accrights = (caddr_t)&fd;
+    arg.msg.msg_accrightslen = sizeof(fd);
 #endif
 
-    if (sendmsg(fptr->fd, &msg, 0) == -1)
+    arg.fd = fptr->fd;
+    if ((int)BLOCKING_REGION(sendmsg_blocking, &arg) == -1)
 	rb_sys_fail("sendmsg(2)");
 
@@ -1986,4 +2047,11 @@ unix_send_io(VALUE sock, VALUE val)
 
 static VALUE
+recvmsg_blocking(void *data)
+{
+    struct iomsg_arg *arg = data;
+    return recvmsg(arg->fd, &arg->msg, 0);
+}
+
+static VALUE
 unix_recv_io(int argc, VALUE *argv, VALUE sock)
 {
@@ -1991,5 +2059,5 @@ unix_recv_io(int argc, VALUE *argv, VALU
     VALUE klass, mode;
     rb_io_t *fptr;
-    struct msghdr msg;
+    struct iomsg_arg arg;
     struct iovec vec[2];
     char buf[1];
@@ -2011,18 +2079,16 @@ unix_recv_io(int argc, VALUE *argv, VALU
     GetOpenFile(sock, fptr);
 
-    rb_io_wait_readable(fptr->fd);
-
-    msg.msg_name = NULL;
-    msg.msg_namelen = 0;
+    arg.msg.msg_name = NULL;
+    arg.msg.msg_namelen = 0;
 
     vec[0].iov_base = buf;
     vec[0].iov_len = sizeof(buf);
-    msg.msg_iov = vec;
-    msg.msg_iovlen = 1;
+    arg.msg.msg_iov = vec;
+    arg.msg.msg_iovlen = 1;
 
 #if FD_PASSING_BY_MSG_CONTROL
-    msg.msg_control = (caddr_t)&cmsg;
-    msg.msg_controllen = CMSG_SPACE(sizeof(int));
-    msg.msg_flags = 0;
+    arg.msg.msg_control = (caddr_t)&cmsg;
+    arg.msg.msg_controllen = CMSG_SPACE(sizeof(int));
+    arg.msg.msg_flags = 0;
     cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(int));
     cmsg.hdr.cmsg_level = SOL_SOCKET;
@@ -2030,17 +2096,18 @@ unix_recv_io(int argc, VALUE *argv, VALU
     *(int *)CMSG_DATA(&cmsg.hdr) = -1;
 #else
-    msg.msg_accrights = (caddr_t)&fd;
-    msg.msg_accrightslen = sizeof(fd);
+    arg.msg.msg_accrights = (caddr_t)&fd;
+    arg.msg.msg_accrightslen = sizeof(fd);
     fd = -1;
 #endif
 
-    if (recvmsg(fptr->fd, &msg, 0) == -1)
+    arg.fd = fptr->fd;
+    if ((int)BLOCKING_REGION(recvmsg_blocking, &arg) == -1)
 	rb_sys_fail("recvmsg(2)");
 
 #if FD_PASSING_BY_MSG_CONTROL
-    if (msg.msg_controllen != CMSG_SPACE(sizeof(int))) {
+    if (arg.msg.msg_controllen != CMSG_SPACE(sizeof(int))) {
       rb_raise(rb_eSocket,
           "file descriptor was not passed (msg_controllen=%d, %d expected)",
-          msg.msg_controllen, CMSG_SPACE(sizeof(int)));
+		 arg.msg.msg_controllen, CMSG_SPACE(sizeof(int)));
     }
     if (cmsg.hdr.cmsg_len != CMSG_LEN(sizeof(int))) {
@@ -2060,8 +2127,8 @@ unix_recv_io(int argc, VALUE *argv, VALU
     }
 #else
-    if (msg.msg_accrightslen != sizeof(fd)) {
+    if (arg.msg.msg_accrightslen != sizeof(fd)) {
 	rb_raise(rb_eSocket,
             "file descriptor was not passed (accrightslen) : %d != %d",
-            msg.msg_accrightslen, sizeof(fd));
+		 arg.msg.msg_accrightslen, sizeof(fd));
     }
 #endif

 
--- 僕の前にBugはない。
--- 僕の後ろにBugはできる。
    中田 伸悦

In This Thread