なかだです。

http://rryu.sakura.ne.jp/nisenise-fuhito/2008/04/22/950.html と
か(見落としてましたが)[ruby-list:43356]にある、接続が切れたソケッ
トに書き込もうとすると、二度目以降selectの待ち状態から抜けなくな
る問題のパッチです。rb_io_wait_{read,writ}able()の互換性がなくなっ
てしまうのが気になるので、名前を変えたほうがいいかもしれませんが、
どういうのがいいですかねぇ。


Index: include/ruby/io.h =================================================================== --- include/ruby/io.h (revision 16258) +++ include/ruby/io.h (working copy) @@ -61,4 +61,5 @@ typedef struct rb_io_t { #define FMODE_TTY 16 #define FMODE_DUPLEX 32 +#define FMODE_BROKENPIPE 256 #define FMODE_WSPLIT 0x200 #define FMODE_WSPLIT_INITIALIZED 0x400 @@ -107,6 +108,6 @@ void rb_io_synchronized(rb_io_t*); void rb_io_check_initialized(rb_io_t*); void rb_io_check_closed(rb_io_t*); -int rb_io_wait_readable(int); -int rb_io_wait_writable(int); +int rb_io_wait_readable(rb_io_t*); +int rb_io_wait_writable(rb_io_t*); void rb_io_set_nonblock(rb_io_t *fptr); Index: io.c =================================================================== --- io.c (revision 16258) +++ io.c (working copy) @@ -419,4 +419,10 @@ rb_io_check_writable(rb_io_t *fptr) rb_raise(rb_eIOError, "not opened for writing"); } +#ifdef __linux__ + if (fptr->mode & FMODE_BROKENPIPE) { + errno = EPIPE; + rb_sys_fail(0); + } +#endif if (fptr->rbuf_len) { io_unread(fptr); @@ -590,5 +596,5 @@ io_fflush(rb_io_t *fptr) errno = EAGAIN; } - if (rb_io_wait_writable(fptr->fd)) { + if (rb_io_wait_writable(fptr)) { rb_io_check_closed(fptr); goto retry; @@ -608,7 +614,8 @@ wait_readable(VALUE p) int -rb_io_wait_readable(int f) +rb_io_wait_readable(rb_io_t *fptr) { rb_fdset_t rfds; + int f = fptr->fd; switch (errno) { @@ -650,7 +657,8 @@ wait_writable(VALUE p) int -rb_io_wait_writable(int f) +rb_io_wait_writable(rb_io_t *fptr) { rb_fdset_t wfds; + int f = fptr->fd; switch (errno) { @@ -676,4 +684,7 @@ rb_io_wait_writable(int f) return Qtrue; + case EPIPE: + fptr->mode |= FMODE_BROKENPIPE; + default: return Qfalse; @@ -752,5 +763,5 @@ io_fwrite(VALUE str, rb_io_t *fptr) errno = EAGAIN; } - if (rb_io_wait_writable(fptr->fd)) { + if (rb_io_wait_writable(fptr)) { rb_io_check_closed(fptr); if (offset < RSTRING_LEN(str)) @@ -1038,5 +1049,5 @@ io_fillbuf(rb_io_t *fptr) } if (r < 0) { - if (rb_io_wait_readable(fptr->fd)) + if (rb_io_wait_readable(fptr)) goto retry; rb_sys_fail(fptr->path); @@ -1480,5 +1491,5 @@ io_getpartial(int argc, VALUE *argv, VAL } if (n < 0) { - if (!nonblock && rb_io_wait_readable(fptr->fd)) + if (!nonblock && rb_io_wait_readable(fptr)) goto again; rb_sys_fail(fptr->path); Index: ext/socket/socket.c =================================================================== --- ext/socket/socket.c (revision 16258) +++ ext/socket/socket.c (working copy) @@ -525,5 +525,5 @@ bsock_send(int argc, VALUE *argv, VALUE } if (n < 0) { - if (rb_io_wait_writable(fd)) { + if (rb_io_wait_writable(fptr)) { goto retry; } @@ -1809,5 +1809,5 @@ udp_send(int argc, VALUE *argv, VALUE so return INT2FIX(n); } - if (rb_io_wait_writable(fptr->fd)) { + if (rb_io_wait_writable(fptr)) { goto retry; } Index: ext/openssl/ossl_ssl.c =================================================================== --- ext/openssl/ossl_ssl.c (revision 16258) +++ ext/openssl/ossl_ssl.c (working copy) @@ -951,8 +951,8 @@ ossl_start_ssl(VALUE self, int (*func)() switch((ret2 = ssl_get_error(ssl, ret))){ case SSL_ERROR_WANT_WRITE: - rb_io_wait_writable(FPTR_TO_FD(fptr)); + rb_io_wait_writable(fptr); continue; case SSL_ERROR_WANT_READ: - rb_io_wait_readable(FPTR_TO_FD(fptr)); + rb_io_wait_readable(fptr); continue; case SSL_ERROR_SYSCALL: @@ -1033,8 +1033,8 @@ ossl_ssl_read(int argc, VALUE *argv, VAL rb_eof_error(); case SSL_ERROR_WANT_WRITE: - rb_io_wait_writable(FPTR_TO_FD(fptr)); + rb_io_wait_writable(fptr); continue; case SSL_ERROR_WANT_READ: - rb_io_wait_readable(FPTR_TO_FD(fptr)); + rb_io_wait_readable(fptr); continue; case SSL_ERROR_SYSCALL: @@ -1081,8 +1081,8 @@ ossl_ssl_write(VALUE self, VALUE str) goto end; case SSL_ERROR_WANT_WRITE: - rb_io_wait_writable(FPTR_TO_FD(fptr)); + rb_io_wait_writable(fptr); continue; case SSL_ERROR_WANT_READ: - rb_io_wait_readable(FPTR_TO_FD(fptr)); + rb_io_wait_readable(fptr); continue; case SSL_ERROR_SYSCALL:
-- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦