[Bug:trunk] TCPServer#gets gets stuck

e$B1sF#$G$9!#e(B

e$BC10l%9%l%C%I$N>uBV$Ge(B TCPServer#gets e$B$r8F$V$He(B Errno::ENOTCONN
e$B$,e(B
e$BEj$2$i$l$^$9$,!“J#?t$N%9%l%C%I$,$$$k>uBV$@$H@\B3$,$”$k$^$G%V%m%C%/e(B
e$B$7$^$9!#e(B

Thread.new { sleep }
TCPServer.new(0).gets

rubyspec e$B$,$=$&$$$&%F%9%H$rF~$l$F$/$l$?$N$G:$$C$F$^$9!#e(B

e$B860x$Oe(B gets e$B$,FI$9~$$r9T$&A0$Ke(B (rb_thread_wait_fd
e$B7PM3$Ge(B) select
e$B$r9T$&$3$H$G$9!#e(B
io.c e$B$Ne(B READ_CHECK e$B$NCf$Ge(B rb_thread_wait_fd
e$B$r8F$VI,MW$O$"$k$N$Ge(B
e$B$7$g$&$+!#!Ve(Bwindows e$B$GI,MW!W$H$Ne(B akr
e$B$5$s$N$*9p$2$,$"$C$?$N$G!"e(B
WIN32 e$B0J30$G$O8F$P$J$$$h$&$K$9$k%Q%C%A$r:n$C$F$$^$7$?!#e(B

make check e$B$He(B test-rubyspec e$B$G$OLdBj$,8+$D$+$j$^$;$s$G$7$?!#e(B
e$B@53N$K$Oe(B 2
e$B$D$[$I%F%9%H$,<:GT$7$^$9$,!"`tKv$JLdBj$J$N$G!"$A$g$C$He(B
e$B=$@5$9$l$PD>$;$^$9!#$I$&$G$7$g$&!#e(B

diff --git a/io.c b/io.c
index 4017778…8b68603 100644
— a/io.c
+++ b/io.c
@@ -175,9 +175,15 @@ static int max_file_descriptor = NOFILE;
#define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf+(fptr)->rbuf_off)
#define READ_DATA_BUFFERED(fptr) READ_DATA_PENDING(fptr)

+#if defined(_WIN32)
+#define WAIT_FD_IN_WIN32(fptr) rb_thread_wait_fd((fptr)->fd);
+#else
+#define WAIT_FD_IN_WIN32(fptr) ;
+#endif
+
#define READ_CHECK(fptr) do {
if (!READ_DATA_PENDING(fptr)) {\

  • rb_thread_wait_fd((fptr)->fd);\
  • WAIT_FD_IN_WIN32(fptr);
    rb_io_check_closed(fptr);
    }
    } while(0)
    @@ -1637,8 +1643,7 @@ fill_cbuf(rb_io_t *fptr, int ec_flags)

      if (res == econv_source_buffer_empty) {
          if (fptr->rbuf_len == 0) {
    
  •            rb_thread_wait_fd(fptr->fd);
    
  •            rb_io_check_closed(fptr);
    
  • READ_CHECK(fptr);
    if (io_fillbuf(fptr) == -1) {
    ds = dp = (unsigned char *)fptr->cbuf +
    fptr->cbuf_off + fptr->cbuf_len;
    de = (unsigned char *)fptr->cbuf + fptr->cbuf_capa;
    @@ -2228,8 +2233,7 @@ appendline(rb_io_t *fptr, int delim, VALUE
    *strp, long *lp)
    if (limit == 0)
    return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
    }
  • rb_thread_wait_fd(fptr->fd);
  • rb_io_check_closed(fptr);
  • READ_CHECK(fptr);
    } while (io_fillbuf(fptr) >= 0);
    *lp = limit;
    return EOF;
    @@ -2251,8 +2255,7 @@ swallow(rb_io_t fptr, int term)
    if (!read_buffered_data(buf, cnt - i, fptr)) /
    must not fail */
    rb_sys_fail_path(fptr->pathv);
    }
  • rb_thread_wait_fd(fptr->fd);
  • rb_io_check_closed(fptr);
  • READ_CHECK(fptr);
    } while (io_fillbuf(fptr) == 0);
    return FALSE;
    }
    @@ -2290,8 +2293,7 @@ rb_io_getline_fast(rb_io_t *fptr, rb_encoding
    *enc)
    pos = rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos,
    RSTRING_PTR(str) + len, enc, &cr);
    if (e) break;
    }
  • rb_thread_wait_fd(fptr->fd);
  • rb_io_check_closed(fptr);
  • READ_CHECK(fptr);
    if (io_fillbuf(fptr) < 0) {
    if (NIL_P(str)) return Qnil;
    break;

2010e$BG/e(B2e$B7ne(B5e$BF|e(B0:18 Yusuke ENDOH [email protected]:

WIN32 e$B0J30$G$O8F$P$J$$$h$&$K$9$k%Q%C%A$r:n$C$F$$^$7$?!#e(B

e$B4D6-$K$h$C$F$OLdBj$,;D$k$H$$$&OC$G$7$g$&$+!#e(B

e$B1sF#$G$9!#e(B

2010e$BG/e(B2e$B7ne(B5e$BF|e(B10:50 Tanaka A. [email protected]:

2010e$BG/e(B2e$B7ne(B5e$BF|e(B0:18 Yusuke ENDOH [email protected]:

WIN32 e$B0J30$G$O8F$P$J$$$h$&$K$9$k%Q%C%A$r:n$C$F$$^$7$?!#e(B

e$B4D6-$K$h$C$F$OLdBj$,;D$k$H$$$&OC$G$7$g$&$+!#e(B

e$B$=$&$$$&$3$H$K$J$k$H;W$$$^$9!#e(B
windows e$B$G$bC/$+$,D>$;$k$J$iD>$;$P$$$$$G$9$7!"=EBg$JLdBj$G$O$J$$e(B
e$B$N$Ge(B best effort e$B$J4D6-$G$OL5;k$7$F$b$$$$$+$H;W$$$^$9!#e(B

e$B!V=EBg$G$J$$$J$i$I$N4D6-$G$bL5;k$9$l$P$$$$!W$H$$$&$J$i!“!V$3$l$Oe(B
e$B;EMMe(B (implementation-defined or dependent) e$B$G$”$j!“e(Brubyspec
e$B$Ke(B
e$B=q$/$Y$-$G$O$J$$!W$H$$$&8"0R$”$k$*8@MU$5$(D:$1$l$P!";d$O$=$l$Ge(B
e$B9=$$$^$;$s!#e(Brubyspec
e$B$+$iEv3:%F%9%H$r>C$9:,5r$K$J$j$^$9$N$G!#e(B

2010e$BG/e(B2e$B7ne(B5e$BF|e(B12:21 Yusuke ENDOH [email protected]:

e$B4D6-$K$h$C$F$OLdBj$,;D$k$H$$$&OC$G$7$g$&$+!#e(B

e$B$=$&$$$&$3$H$K$J$k$H;W$$$^$9!#e(B
windows e$B$G$bC/$+$,D>$;$k$J$iD>$;$P$$$$$G$9$7!"=EBg$JLdBj$G$O$J$$e(B
e$B$N$Ge(B best effort e$B$J4D6-$G$OL5;k$7$F$b$$$$$+$H;W$$$^$9!#e(B

1.8 e$B$O$I$&$7$^$9e(B?

% ruby-1.8 -rsocket -ve ’
Thread.new { sleep }
TCPServer.new(0).gets

ruby 1.8.8dev (2010-01-13 revision 26317) [i686-linux]

e$B1sF#$G$9!#e(B

2010e$BG/e(B2e$B7ne(B5e$BF|e(B14:05 Tanaka A. [email protected]:

2010e$BG/e(B2e$B7ne(B5e$BF|e(B12:21 Yusuke ENDOH [email protected]:

e$B4D6-$K$h$C$F$OLdBj$,;D$k$H$$$&OC$G$7$g$&$+!#e(B

e$B$=$&$$$&$3$H$K$J$k$H;W$$$^$9!#e(B
windows e$B$G$bC/$+$,D>$;$k$J$iD>$;$P$$$$$G$9$7!"=EBg$JLdBj$G$O$J$$e(B
e$B$N$Ge(B best effort e$B$J4D6-$G$OL5;k$7$F$b$$$$$+$H;W$$$^$9!#e(B

1.8 e$B$O$I$&$7$^$9e(B?

e$B$“$”!“$=$s$J$b$N$b$”$j$^$7$?$M$(!#A4$/8+$F$^$;$s!#e(B

windows e$B$HF1MM$K!“$=$l$O$=$l$G9M$($l$P$$$$$H;W$$$^$9!#e(B
1.8 e$B$He(B 1.9
e$B$,F1$8%”%W%m!<%A$G2r7h$G$-$k$J$i$=$l$,$h$5$=$&$G$9$,!"e(B
1.8 e$B$G%@%a$@$+$i$H$$$C$Fe(B 1.9
e$B$G$b2r7h$7$J$$$H$$$&M}M3$b$J$$$He(B
e$B;W$$$^$9!#e(B

e$B$=$l$G$b$d$O$j!Ve(B1.8
e$B$G2r7h$G$-$J$$$+$i%@%a$@!W$H$$$&$3$H$J$i!“e(B
e$B!V$3$l$,;EMM$G$”$je(B rubyspec
e$B$K=q$/$Y$-$G$J$$!W$H8@$C$F$/$@$5$$!#e(B
e$B$*4j$$$7$^$9!#e(B

2010e$BG/e(B2e$B7ne(B9e$BF|e(B22:23 Yusuke ENDOH [email protected]:

akr e$B$5$s$N;XE&$9$kLdBje(B (windows e$B$He(B 1.8) e$B$O;D$k$N$G!"$h$j$h$$e(B
e$B2r7h:v$NDs0F$rBT$C$F$$$^$9!#e(B

e$B;W$$$D$$$?$s$G$9$,!"e(BRubinius e$B$O$I$&$J$s$G$9$+$M!#e(B

e$B1sF#$G$9!#e(B

2010e$BG/e(B2e$B7ne(B5e$BF|e(B0:18 Yusuke ENDOH [email protected]:

e$B$7$g$&$+!#!Ve(Bwindows e$B$GI,MW!W$H$Ne(B akr e$B$5$s$N$*9p$2$,$"$C$?$N$G!"e(B
WIN32 e$B0J30$G$O8F$P$J$$$h$&$K$9$k%Q%C%A$r:n$C$F$$^$7$?!#e(B

e$BD>@\E*$JH?BP$O$J$$$h$&$J$N$G!"0lC6%3%_%C%H$7$^$9!#e(B

e$B$H$$$C$F$b$3$N%Q%C%A$G@5$7$$$+$I$&$+$O$+$J$j<+?.$J$$$N$G!“e(BIO
e$B<~$j$GJQ$H$+8G$^$k$H$+$K$J$C$?$i!”$3$N7o$r5?$C$F$/$@$5$$!#e(B

akr e$B$5$s$N;XE&$9$kLdBje(B (windows e$B$He(B 1.8)
e$B$O;D$k$N$G!"$h$j$h$$e(B
e$B2r7h:v$NDs0F$rBT$C$F$$$^$9!#e(B

2010e$BG/e(B2e$B7ne(B9e$BF|e(B22:23 Yusuke ENDOH [email protected]:

e$B$H$$$C$F$b$3$N%Q%C%A$G@5$7$$$+$I$&$+$O$+$J$j<+?.$J$$$N$G!“e(BIO
e$B<~$j$GJQ$H$+8G$^$k$H$+$K$J$C$?$i!”$3$N7o$r5?$C$F$/$@$5$$!#e(B

test-all e$B$G<:GT$,A}$($F$$$^$9$M!#e(B

% ./ruby -v test/ruby/test_io.rb
ruby 1.9.2dev (2010-02-11 trunk 26640) [i686-linux]
Loaded suite test/ruby/test_io
Started
…F…F…
Finished in 1.087307 seconds.

  1. Failure:
    test_read_error(TestIO) [test/ruby/test_io.rb:869]:
    RuntimeError expected but nothing was raised.

  2. Failure:
    test_readpartial_error(TestIO) [test/ruby/test_io.rb:834]:
    RuntimeError expected but nothing was raised.

85 tests, 336 assertions, 2 failures, 0 errors, 0 skips

e$B<:GT$9$k%F%9%H$r$A$g$C$HJQ$($k$H!"0J2<$N$h$&$Ke(B EFAULT
e$B$r5/$3$;$^$9!#e(B

% ./ruby -ve ’
r, w = IO.pipe
n = 1000000
s = “”
t = Thread.new { r.readpartial(n, s) }
0 until s.size == n
s.clear
w.write “a”
p t.join

ruby 1.9.2dev (2010-02-11 trunk 26640) [i686-linux]
-e:5:in readpartial': Bad address (Errno::EFAULT) from -e:5:in block in ’

e$B$^$!!“$3$l$OMn$A$J$1$l$P$$$$$H$$$&N`$NOC$G!”$$$^$N$H$3$mMn$A$F$$$J$$$N$Ge(B
e$B$$$$$H$$$($P$$$$$N$G$9$,!"4m81$K6a$E$$$F$$$k5$$O$7$^$9!#e(B

e$BMn$A$F$$$J$$$N$G!"$^$@%P%0$G$O$J$$$H9M$($F$$$^$9$,!"e(B
e$B5-O?$N$?$a$K=q$$$F$*$-$^$9!#e(B

e$B1sF#$G$9!#e(B

e$BO"Ej$9$_$^$;$s!#e(B

2010e$BG/e(B2e$B7ne(B11e$BF|e(B17:14 Yusuke ENDOH [email protected]:

  • read e$B$K%P%C%U%!$rL@<($7$FBT$A>uBV$K$7!"e(B
  • read e$BJ,$KK~$?$J$$$@$1e(B write e$B$7$Fe(B (e$B$3$l$G%A%'%C%/$r$+$o$;$ke(B)
  • e$B%P%C%U%!$re(B modify e$B$7$?8e$Ge(B
  • write e$B$7$F$bNc30$,>e$,$i$:JQ$J$3$H$K$J$ke(B (e$B$3$H$,$"$ke(B)

e$B$H$$$&$o$1$G!"$3$N%A%'%C%/$K$O:#$N$H$3$m0UL#$,$J$$$H;W$$$^$9!#e(B

e$B$3$N%A%‘%C%/2sHr$N%“%W%m!<%A$G!”$a$G$?$/:#2s$NJQ99A0$G$bMn$H$;$ke(B
e$B$3$H$,3NG’$G$-$^$7$?!#e(B

$ cat t.rb
r, w = IO.pipe
s = “”
n = 10000
w.write(“foo”)
t = Thread.new { r.read(n, s) }
(sleep 1; p [s[0, 5], s.size]) until s.size == n
s.clear
w.write(“barbaz” * 1000)
w.close
t.join

$ ruby-1.9.1-p378 t.rb
[“foo\x00\x00”, 10000]
t.rb:9: [BUG] Segmentation fault
ruby 1.9.1p378 (2010-01-10 revision 26273) [i686-linux]

– control frame ----------
c:0003 p:0182 s:0012 b:0011 l:001784 d:002150 EVAL t.rb:9
c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH
c:0001 p:0000 s:0002 b:0002 l:001784 d:001784 TOP

e$B%;%0%a%s%F!<%7%g%s0cH?$G$9e(B

e$B:F8=@-$O$"$^$j9b$/$J$$$h$&$G$9e(B (20 e$B2s$Ke(B 1 e$B2s$/$i$$!)e(B)
e$B!#e(B

e$B$d$k$H$7$?$i!“e(Bio_read e$B$NCf$Ne(B READ_CHECK e$B$ND>8e$@$1$G%A%‘%C%/$7$F$be(B
e$B$@$a$G!"e(Bbuffer string e$B$K=q$3$&$H$9$kD>A0$GKh2s%A%’%C%/$9$kI,MW$,e(B
e$B$”$k$H;W$$$^$9$,!“e(BIO e$B$N%Q%U%)!<%^%s%9$,2<$,$j$=$&$J$N$G$=$3$^$G$9$ke(B
e$BI,MW$,$”$k$+$I$&$+$O$o$+$j$^$;$s!#e(B

e$B$N$h$&$K!":#2s$NJQ99$H$O4X78$J$/!“e(Bio_fread
e$B$J$I$N<B9TCf$KJ8;zNs$,$$$8$i$l$Fe(B
e$B$$$J$$$+%A%'%C%/$9$kI,MW$,$”$j$=$&$G$9!#e(B

e$B1sF#$G$9!#e(B

2010e$BG/e(B2e$B7ne(B11e$BF|e(B16:46 Tanaka A. [email protected]:

Started

85 tests, 336 assertions, 2 failures, 0 errors, 0 skips

e$B$“$”$=$&$@!"K:$l$F$^$7$?!#$=$l$,!V`tKv$JLdBj!W$H$$$C$?$d$D$G$9!#e(B
e$B$b$H$b$H$Oe(B

$ ruby-1.9.1-p378 -e ’
r, w = IO.pipe
s = “”
t = Thread.new { r.read(5, s) }
0 until s.size == 5
s.clear
w.write “foobarbaz”
w.close
t.join

-e:4:in read': buffer string modified (RuntimeError) from -e:4:in block in ’

e$B$N$h$&$K!"e(B

  • read e$B$K%P%C%U%!$rL@<($7$FBT$A>uBV$K$7!"e(B
  • e$B%P%C%U%!$re(B modify e$B$7$?8e$Ge(B
  • write e$B$7$?$iNc30$,>e$,$k!"e(B

e$B$H$$$&5sF0$@$C$?$N$G$9$,!“0J2<$N$h$&$K$9$k$H!”$3$N%A%'%C%/$Oe(B
e$BH4$1$i$l$k$3$H$,$"$j$^$9e(B (e$B%?%$%_%s%0$K0MB8$7$^$9$,e(B) e$B!#e(B

$ ruby-1.9.1-p378 -e ’
r, w = IO.pipe
s = “”
w.write “foo”
t = Thread.new { r.read(5, s) }
0 until s.size >= 5
p s
s.clear
w.write “barbaz”
w.close
t.join
p s

“\x00ooba”

e$B$D$^$j!"e(B

  • read e$B$K%P%C%U%!$rL@<($7$FBT$A>uBV$K$7!"e(B
  • read e$BJ,$KK~$?$J$$$@$1e(B write e$B$7$Fe(B
    (e$B$3$l$G%A%'%C%/$r$+$o$;$ke(B)
  • e$B%P%C%U%!$re(B modify e$B$7$?8e$Ge(B
  • write e$B$7$F$bNc30$,>e$,$i$:JQ$J$3$H$K$J$ke(B (e$B$3$H$,$"$ke(B)

e$B$H$$$&$o$1$G!"$3$N%A%'%C%/$K$O:#$N$H$3$m0UL#$,$J$$$H;W$$$^$9!#e(B

e$B$d$k$H$7$?$i!“e(Bio_read e$B$NCf$Ne(B READ_CHECK
e$B$ND>8e$@$1$G%A%‘%C%/$7$F$be(B
e$B$@$a$G!"e(Bbuffer string
e$B$K=q$3$&$H$9$kD>A0$GKh2s%A%’%C%/$9$kI,MW$,e(B
e$B$”$k$H;W$$$^$9$,!“e(BIO
e$B$N%Q%U%)!<%^%s%9$,2<$,$j$=$&$J$N$G$=$3$^$G$9$ke(B
e$BI,MW$,$”$k$+$I$&$+$O$o$+$j$^$;$s!#e(B

e$B$H8@$&$o$1$G!"H?BP$,$J$1$l$P$3$N%A%'%C%/$H%F%9%H$O30$7$F$7$^$*$&$He(B
e$B;W$C$F$$$^$9!#e(B

e$B$^$!!“$3$l$OMn$A$J$1$l$P$$$$$H$$$&N`$NOC$G!”$$$^$N$H$3$mMn$A$F$$$J$$$N$Ge(B
e$B$$$$$H$$$($P$$$$$N$G$9$,!"4m81$K6a$E$$$F$$$k5$$O$7$^$9!#e(B

e$B$J$s$H$+$G$-$k$H$$$$$s$G$9$1$I$M$(!#e(B

e$B2?EY$b8@$C$F$$$^$9$,!“!V0BA4B&$KE]$7$Fe(B TCPServer#gets
e$B$,8G$^$k$3$H$,e(B
e$B$”$k$N$O;EMM$H$9$k!W$H8@$C$F$/$l$k$N$G$b;d$O9=$$$^$;$s!#e(B

e$B3N$+$K!"e(Brubyspec e$B$N?M$?$A$be(B 1.8 e$B$H$+$Ge(B rubinius
e$B$H$+$G8G$^$C$F$J$$$Ne(B
e$B$+IT;W5D$G$9$h$M!#:#EYJ9$$$H$-$^$9!#e(B

2010e$BG/e(B2e$B7ne(B11e$BF|e(B17:14 Yusuke ENDOH [email protected]:

e$B$H$$$&5sF0$@$C$?$N$G$9$,!“0J2<$N$h$&$K$9$k$H!”$3$N%A%'%C%/$Oe(B
e$BH4$1$i$l$k$3$H$,$"$j$^$9e(B (e$B%?%$%_%s%0$K0MB8$7$^$9$,e(B) e$B!#e(B

e$B$Y$D$KMn$A$J$1$l$P$$$$$s$G$9$,!#e(B
e$B%F%9%H$,$"$k$N$O!"0JA0!"Mn$A$?$+$i$N$h$&$J5$$,$7$^$9!#e(B

e$B$d$k$H$7$?$i!“e(Bio_read e$B$NCf$Ne(B READ_CHECK e$B$ND>8e$@$1$G%A%‘%C%/$7$F$be(B
e$B$@$a$G!"e(Bbuffer string e$B$K=q$3$&$H$9$kD>A0$GKh2s%A%’%C%/$9$kI,MW$,e(B
e$B$”$k$H;W$$$^$9$,!“e(BIO e$B$N%Q%U%)!<%^%s%9$,2<$,$j$=$&$J$N$G$=$3$^$G$9$ke(B
e$BI,MW$,$”$k$+$I$&$+$O$o$+$j$^$;$s!#e(B

EFAULT e$B$N%1!<%9$@$H!“e(Bbuffer string e$B$K=q$/$N$Oe(B read
e$B%7%9%F%%3!<%k$J$N$G!"e(B e$B%+!<%M%k$,e(B EFAULT e$B$G:Q$^$7$F$/$l$k$H$$$&$N$r4|BT$9$k$3$H$K$J$j$^$9$M!#e(B e$B%7%9%F%%3!<%k$rH/9T$9$kA0$K$O%a%b%j$O$A$c$s$H$”$C$F8!::$N$7$h$&$,$J$$$7!#e(B
e$B$=$l$G$O:Q$^$J$$e(B OS
e$B$,L5$$$3$H$r4|BT$9$k!"$H$$$&$3$H$K$J$j$^$9$+$M!#e(B

read
e$B$,%f!<%6%l%Y%k$N4X?t$G!"%P%C%U%!$K=q$-9~$`$H$+$5$l$k$HMn$A$=$&$J5$$,!#e(B

e$B$$$d!“%7%9%F%`%3!<%k$G$”$C$F$b!“e(B
e$B%a%b%j$r2rJ|$7$?8e$^$?B>$NMQES$G3NJ]$7$?$i%”%I%l%9$,F1$8$K$J$C$A$c$C$Fe(B
e$B$=$3$Ke(B read
e$B$,=q$-9~$s$G2u$7$F$7$^$&$H$$$&2DG=@-$O$I$&$@$m$&e(B?

STR_TMPLOCK e$B$,;H$($k$+$J$!!#e(B

e$B3N$+$K!"e(Brubyspec e$B$N?M$?$A$be(B 1.8 e$B$H$+$Ge(B rubinius e$B$H$+$G8G$^$C$F$J$$$Ne(B
e$B$+IT;W5D$G$9$h$M!#:#EYJ9$$$H$-$^$9!#e(B

e$B3NG’$7$F$^$;$s$,!"B>$K%9%l%C%I$,L5$$$N$G$Oe(B?

e$B$^$!!"e(B1.9
e$B$N>l9g$KB8:_$9$k%9%l%C%I$O2?$+$H$$$&$N$b3NG’$7$F$^$;$s$,!#e(B

e$B1sF#$G$9!#e(B

2010e$BG/e(B2e$B7ne(B11e$BF|e(B17:35 Tanaka A. [email protected]:

2010e$BG/e(B2e$B7ne(B11e$BF|e(B17:14 Yusuke ENDOH [email protected]:

e$B$H$$$&5sF0$@$C$?$N$G$9$,!“0J2<$N$h$&$K$9$k$H!”$3$N%A%'%C%/$Oe(B
e$BH4$1$i$l$k$3$H$,$"$j$^$9e(B (e$B%?%$%_%s%0$K0MB8$7$^$9$,e(B) e$B!#e(B

e$B$Y$D$KMn$A$J$1$l$P$$$$$s$G$9$,!#e(B
e$B%F%9%H$,$"$k$N$O!"0JA0!"Mn$A$?$+$i$N$h$&$J5$$,$7$^$9!#e(B

e$B$$$(!"LdBj$N%F%9%H$OC1$K%+%P%l%C%8$N$?$a$Ke(B r16683
e$B$G;d$,F~$l$?$b$N$G$9!#e(B

e$B$d$k$H$7$?$i!“e(Bio_read e$B$NCf$Ne(B READ_CHECK e$B$ND>8e$@$1$G%A%‘%C%/$7$F$be(B
e$B$@$a$G!"e(Bbuffer string e$B$K=q$3$&$H$9$kD>A0$GKh2s%A%’%C%/$9$kI,MW$,e(B
e$B$”$k$H;W$$$^$9$,!“e(BIO e$B$N%Q%U%)!<%^%s%9$,2<$,$j$=$&$J$N$G$=$3$^$G$9$ke(B
e$BI,MW$,$”$k$+$I$&$+$O$o$+$j$^$;$s!#e(B

EFAULT e$B$N%1!<%9$@$H!“e(Bbuffer string e$B$K=q$/$N$Oe(B read e$B%7%9%F%%3!<%k$J$N$G!"e(B e$B%+!<%M%k$,e(B EFAULT e$B$G:Q$^$7$F$/$l$k$H$$$&$N$r4|BT$9$k$3$H$K$J$j$^$9$M!#e(B e$B%7%9%F%%3!<%k$rH/9T$9$kA0$K$O%a%b%j$O$A$c$s$H$”$C$F8!::$N$7$h$&$,$J$$$7!#e(B
e$B$=$l$G$O:Q$^$J$$e(B OS e$B$,L5$$$3$H$r4|BT$9$k!"$H$$$&$3$H$K$J$j$^$9$+$M!#e(B

e$B$=$&$G$7$?!#e(Bio_fread e$B$NCf$G%A%'%C%/$7$F$b%@%a$G$9$M!#e(B

EFAULT e$B$C$F$I$N$/$i$$$“$F$K$J$k$s$G$7$g$&$M!#e(Bread
e$BH/9TD>8e$O$A$c$s$He(B
e$B%P%C%U%!$,$”$C$?$1$I!“%V%m%C%/Cf$KJL%9%l%C%I$,e(B free/realloc
e$B$7$?$J$s$Fe(B
e$B$N$b=u$1$F$/$l$k$N$+$J$”!#e(B
e$B<B:]e(B [ruby-dev:40391]
e$B$GMn$A$F$$$k$N$,$=$N$;$$$+$I$&$+$OD4$Y$F$^$;$s!#e(B

STR_TMPLOCK e$B$,;H$($k$+$J$!!#e(B

e$B$=$&$$$($P$=$s$J$b$N$,$"$j$^$7$?$M!#$=$l$,NI$5$=$&!#e(B

e$B3N$+$K!"e(Brubyspec e$B$N?M$?$A$be(B 1.8 e$B$H$+$Ge(B rubinius e$B$H$+$G8G$^$C$F$J$$$Ne(B
e$B$+IT;W5D$G$9$h$M!#:#EYJ9$$$H$-$^$9!#e(B

e$B3NG’$7$F$^$;$s$,!"B>$K%9%l%C%I$,L5$$$N$G$Oe(B?

e$B$^$!!"e(B1.9 e$B$N>l9g$KB8:_$9$k%9%l%C%I$O2?$+$H$$$&$N$b3NG’$7$F$^$;$s$,!#e(B

TCPServer#gets e$B$Ne(B spec
e$B$rC1BN$G<B9T$7$F$b8G$^$i$J$/$F!“e(BNet::HTTP e$B$Ne(B
spec
e$B$H$”$o$;$F<B9T$9$k$H8G$^$C$F$^$7$?!#$J$N$G!"$=$NJU$N%9%l%C%I$,e(B
e$B$?$^$?$^e(B 1.9 e$B$G$O@8$-;D$C$F$$$k$s$G$9$+$Me(B (e$B$b$A$m$se(B
Net::HTTP e$B0J30$Ne(B
e$B%9%l%C%I$b$$$k$+$b$7$l$J$$e(B) e$B!#e(B

e$B$=$b$=$b@8$-;D$k$N$,$*$+$7$$!)e(B

e$B%9%l%C%I%W!<%k$_$?$$$J$3$H$9$k$s$G$7$?$C$1!#e(B

e$B$*$O$h$&$4$6$$$^$9!#e(B

In message [email protected]
on Thu, 11 Feb 2010 18:36:14 +0900,
Yusuke ENDOH [email protected] wrote:

EFAULT e$B$C$F$I$N$/$i$$$“$F$K$J$k$s$G$7$g$&$M!#e(Bread e$BH/9TD>8e$O$A$c$s$He(B
e$B%P%C%U%!$,$”$C$?$1$I!“%V%m%C%/Cf$KJL%9%l%C%I$,e(B free/realloc e$B$7$?$J$s$Fe(B
e$B$N$b=u$1$F$/$l$k$N$+$J$”!#e(B
free(3)/realloc(3)e$B$7$?$H$7$F$b!"%+!<%M%k$+$i8+$F%W%m%;%9$K3d$jEv$F$i$le(B
e$B$?%a%b%j$KJQ$o$j$,$J$1$l$P!"e(BEFALUTe$B$K$O$J$i$J$$$G$7$g$&!#e(B

e$B$3$l$r4|BT$9$kJ}$,!"L5M}$J5$$,$7$^$9!#e(B

kosakiです。

そうでした。io_fread の中でチェックしてもダメですね。

EFAULT ってどのくらいあてになるんでしょうね。read 発行直後はちゃんと
バッファがあったけど、ブロック中に別スレッドが free/realloc したなんて
のも助けてくれるのかなあ。

ちゃんと調べずに書いていますが、カーネル屋さんの基本思想としては、あるプロセスがアホの子の時に
そのプロセスが死ぬのを防ぐ必要はないと考えています。memcpyの引数間違えただけでSIGSEGVする
ã“ã‚“ãªä¸–ã®ä¸­ã˜ã‚ƒã‚«ãƒ¼ãƒãƒ«ã ã‘é ‘å¼µã£ã¦ãƒã‚§ãƒƒã‚¯ã—ã¦ã‚‚ã‚ã‚“ã¾ã‚Šä¾¡å€¤ãªã„ã—ã€‚
ã‚‚ã¡ã‚ã‚“ã€ãƒŸã‚¹ã‚‹ã¨ã‚«ãƒ¼ãƒãƒ«ã¨ã‹ä»–ãƒ—ãƒ­ã‚»ã‚¹ã«è¢«å®³ãŒå‡ºãã†ãªå ´åˆã¯åŽ³å¯†ã«ã‚„ã‚Šã¾ã™ãŒã€‚

そういうわけで、広い世の中きっとSEGVするOSはあるんじゃないかなぁ

e$B1sF#$G$9!#e(B

2010e$BG/e(B2e$B7ne(B12e$BF|e(B9:39 Takahiro K.
[email protected]:

EFAULT e$B$C$F$I$N$/$i$$$“$F$K$J$k$s$G$7$g$&$M!#e(Bread e$BH/9TD>8e$O$A$c$s$He(B
e$B%P%C%U%!$,$”$C$?$1$I!“%V%m%C%/Cf$KJL%9%l%C%I$,e(B free/realloc e$B$7$?$J$s$Fe(B
e$B$N$b=u$1$F$/$l$k$N$+$J$”!#e(B
free(3)/realloc(3)e$B$7$?$H$7$F$b!"%+!<%M%k$+$i8+$F%W%m%;%9$K3d$jEv$F$i$le(B
e$B$?%a%b%j$KJQ$o$j$,$J$1$l$P!"e(BEFALUTe$B$K$O$J$i$J$$$G$7$g$&!#e(B

e$B$3$l$r4|BT$9$kJ}$,!"L5M}$J5$$,$7$^$9!#e(B

e$B$^$“!”$=$j$c$=$&$G$9$h$M!#e(BOS e$B$,e(B libc
e$B%l%Y%k$N>pJs$rCN$kLu$J$$!#e(B

e$B8e$+$i%m%0$rFI$`$R$H$N$?$a$KLdBj$r@0M}$7$F$*$/$H!"e(B

  • EFAULT e$B$de(B SEGV e$B$,5/$-$kLdBj$O85$+$i$"$C$?e(B (1.9.1
    e$B$G$b4QB,$5$le(B
    e$B$F$$$ke(B)

  • SEGV e$B$r5/$-$K$/$/$9$k%A%'%C%/$,$“$C$?$,!”%?%$%_%s%0$r$:$i$;$Pe(B
    e$B4JC1$KH4$1$i$l$k$N$G!"K<AE*$K$O2r7h$5$l$F$$$J$$e(B

  • [ruby-dev:40317] e$B$N%Q%C%A$O%?%$%_%s%0E*$K$3$N%A%'%C%/$N8z2L$re(B
    e$B<e$a$k$?$a!"e(BEFAULT e$B$,4QB,$7$d$9$/$J$C$?e(B

  • e$B85$NLdBj$Oe(B STR_TMPLOCK e$B$r;H$($P$?$V$s$A$c$s$H2r7h$G$-$ke(B

e$B$H$$$&$o$1$G!“e(B[ruby-dev:40317]
e$B$N%Q%C%A$KLdBj$,$”$k$o$1$G$O$J$$e(B
e$B$H9M$($F$$$^$9!#:#$N$H$3$m!#e(B

At Fri, 12 Feb 2010 09:39:30 +0900, Takahiro K. wrote:

free(3)/realloc(3)e$B$7$?$H$7$F$b!"%+!<%M%k$+$i8+$F%W%m%;%9$K3d$jEv$F$i$le(B
e$B$?%a%b%j$KJQ$o$j$,$J$1$l$P!"e(BEFALUTe$B$K$O$J$i$J$$$G$7$g$&!#e(B

FreeBSD(e$B$N$I$l$+e(B?)e$B$Ne(Bfree(3)e$B$O!">u67$K$h$C$Fe(Bmadvise(MADV_DONTNEED)e$B$r;He(B
e$B$$$^$9!#$=$&$$$&>l9g!"!V%W%m%;%9$K3d$jEv$F$i$l$?%a%b%j!W$KJQ$o$j$,$"$Ce(B
e$B$?>l9g$G$9$i2?$b5/$-$^$;$s!#e(B

ISO9899:1999(E)e$B$Ne(B7.20.3.2 The free
functione$B$O$=$NJU$r5,Dj$7$J$$$h$&$Je(B
e$B$N$G!"$=$l$G$b$$$$$s$G$7$g$&!#e(B

e$B1sF#$G$9!#e(B

2010e$BG/e(B2e$B7ne(B12e$BF|e(B12:24 Yusuke ENDOH [email protected]:

  • e$B85$NLdBj$Oe(B STR_TMPLOCK e$B$r;H$($P$?$V$s$A$c$s$H2r7h$G$-$ke(B

e$B$d$C$F$$^$7$?!#e(Bmake check e$B$He(B make test-rubyspec
e$B$O40Av$7$F$$$^$9$,!"e(B
e$B$I$&$G$7$g$&!#H?BP$,$J$1$l$P%3%
%C%H$7$^$9!#e(B

diff --git a/io.c b/io.c
index 9983e17…fd7fbbf 100644
— a/io.c
+++ b/io.c
@@ -1742,7 +1742,9 @@ read_all(rb_io_t *fptr, long siz, VALUE str)
}
for (;:wink: {
READ_CHECK(fptr);

  • rb_str_locktmp(str);
    n = io_fread(str, bytes, fptr);

  • rb_str_unlocktmp(str);
    if (n == 0 && bytes == 0) {
    break;
    }
    @@ -1810,18 +1812,15 @@ io_getpartial(int argc, VALUE *argv, VALUE io,
    int nonblock)

    if (!nonblock)
    READ_CHECK(fptr);

  • if (RSTRING_LEN(str) != len) {
  •  modified:
    
  • rb_raise(rb_eRuntimeError, “buffer string modified”);
  • }
    n = read_buffered_data(RSTRING_PTR(str), len, fptr);
    if (n <= 0) {
    again:
  • if (RSTRING_LEN(str) != len) goto modified;
    if (nonblock) {
    rb_io_set_nonblock(fptr);
    }
  • rb_str_locktmp(str);
    n = rb_read_internal(fptr->fd, RSTRING_PTR(str), len);

  • rb_str_unlocktmp(str);
    if (n < 0) {
    if (!nonblock && rb_io_wait_readable(fptr->fd))
    goto again;
    @@ -2136,10 +2135,9 @@ io_read(int argc, VALUE *argv, VALUE io)
    if (len == 0) return str;

    READ_CHECK(fptr);

  • if (RSTRING_LEN(str) != len) {
  • rb_raise(rb_eRuntimeError, “buffer string modified”);
  • }
  • rb_str_locktmp(str);
    n = io_fread(str, 0, fptr);
  • rb_str_unlocktmp(str);
    if (n == 0) {
    if (fptr->fd < 0) return Qnil;
    rb_str_resize(str, 0);
    @@ -3841,11 +3839,10 @@ rb_io_sysread(int argc, VALUE *argv, VALUE io)
    n = fptr->fd;
    rb_thread_wait_fd(fptr->fd);
    rb_io_check_closed(fptr);
  • if (RSTRING_LEN(str) != ilen) {
  • rb_raise(rb_eRuntimeError, “buffer string modified”);
  • }
  • rb_str_locktmp(str);
    n = rb_read_internal(fptr->fd, RSTRING_PTR(str), ilen);

  • rb_str_unlocktmp(str);

    if (n == -1) {
    rb_sys_fail_path(fptr->pathv);
    diff --git a/test/ruby/test_io.rb b/test/ruby/test_io.rb
    index 0052a92…830bef6 100644
    — a/test/ruby/test_io.rb
    +++ b/test/ruby/test_io.rb
    @@ -823,15 +823,15 @@ class TestIO < Test::Unit::TestCase
    end)
    end

  • def test_readpartial_error
  • def test_readpartial_lock
    with_pipe do |r, w|
    s = “”
    t = Thread.new { r.readpartial(5, s) }
    0 until s.size == 5
  •  s.clear
    
  •  assert_raise(RuntimeError) { s.clear }
     w.write "foobarbaz"
     w.close
    
  •  assert_raise(RuntimeError) { t.join }
    
  •  assert_equal("fooba", t.value)
    
    end
    end

@@ -858,15 +858,15 @@ class TestIO < Test::Unit::TestCase
end)
end

  • def test_read_error
  • def test_read_lock
    with_pipe do |r, w|
    s = “”
    t = Thread.new { r.read(5, s) }
    0 until s.size == 5
  •  s.clear
    
  •  assert_raise(RuntimeError) { s.clear }
     w.write "foobarbaz"
     w.close
    
  •  assert_raise(RuntimeError) { t.join }
    
  •  assert_equal("fooba", t.value)
    
    end
    end

e$B@.@%$G$9!#e(B

(2010/02/17 0:57), Yusuke ENDOH wrote:

e$B$d$C$F$$^$7$?!#e(Bmake check e$B$He(B make test-rubyspec e$B$O40Av$7$F$$$^$9$,!"e(B
e$B$I$&$G$7$g$&!#H?BP$,$J$1$l$P%3%
%C%H$7$^$9!#e(B

e$B<j85$G$b40Av$9$k;v$r3NG’$7$^$7$?!#e(B
e$B$"$j$,$H$&$4$6$$$^$7$?!#e(B