Io/console IO#raw error when io is closed in the block

io/console e$B$r;H$C$F$_$?$N$G$9$,!"$A$g$C$H$&$^$/;H$($^$;$s!#e(B
IO#raw e$B$,e(B tty
e$B$N>uBV$rI,$:85$K$b$I$9$s$G$9$,!"$=$l$,$A$g$C$H:$$j$^$9!#e(B

e$B0J2<$N$h$&$K!"e(Bpty e$B$rDL$7$Fe(B factor
e$B%3%^%s%I$r;H$&$3$H$r9M$($^$9!#e(B

% ./ruby -rpty -e ’
m, s = PTY.open
r, w = IO.pipe
pid = spawn(“factor”, :in=>r, :out=>s)
r.close
s.close
w.puts “42”; p m.gets
w.puts “133”; p m.gets

“42: 2 3 7\r\n”
“133: 7 19\r\n”

42 e$B$He(B 133 e$B$re(B factor
e$B%3%^%s%I$GAG0x?tJ,2r$G$-$F$@$$$?$$$&$^$/$$$C$F$$$^$9$,!"e(B
e$B2~9T$,e(B \r\n e$B$H$J$C$F$7$^$&$N$,5$$KF~$j$^$;$s!#e(B

factor e$B%3%^%s%I<+BN$Oe(B \n e$B$rI8=`=PNO$K=PNO$7$F$*$j!"e(B
e$B$=$l$re(B \r\n e$B$K$7$F$$$k$N$Oe(B tty (pty) e$B$G$9!#e(B

e$B$3$3$G!"e(Bpty e$B$8$c$J$/$Fe(B pipe e$B$H$$$&$o$1$K$O$$$-$^$;$s!#e(B
PTY.open e$B$re(B IO.pipe e$B$KJQ$($FF0$+$;$PJ,$+$j$^$9$,!“e(B
factor e$B%3%^%s%I$,=PNO$r%P%C%U%!%j%s%0$9$k$?$a!”%O%s%0$7$^$9!#e(B
(e$B>/$J$/$H$be(B Debian e$B$Ne(B factor e$B%3%^%s%I$G$Oe(B)

e$B$H$$$&$o$1$G!"$d$C$Q$je(B pty
e$B$J$N$G!"$=$l$G2~9T$NJQ49$rM^@)$9$k$K$Oe(B
io/console e$B$N=PHV$H$$$&$3$H$G!"e(BIO#raw e$B$r;H$&$H!"0J2<$N$h$&$Ke(B
e$B%(%i!<$K$J$C$F$7$^$$$^$9!#e(B

% ./ruby -rpty -rio/console -e ’
m, s = PTY.open
r, w = IO.pipe
s.raw {
pid = spawn(“factor”, :in=>r, :out=>s)
r.close
s.close
w.puts “42”; p m.gets
w.puts “133”; p m.gets
}

“42: 2 3 7\n”
“133: 7 19\n”
-e:4:in raw': closed stream (IOError) from -e:4:in

s e$B$Oe(B spawn e$BD>8e$Ke(B close e$B$7$F$"$k$N$G!"e(Btty
e$B$N>uBV$r85$KLa$=$&$H$7$Fe(B
e$B$9$G$Ke(B close e$B$5$l$F$$$k$H$$$&%(%i!<$K$J$C$F$$$^$9!#e(B

s e$B$re(B close e$B$9$k$3$H$O!"e(Bpipe
e$B$+$iN`?d$9$k$H$$$1$J$/$O$J$$$h$&$K;W$$$^$9!#e(B

IO#raw e$B$G!"%V%m%C%/Fb$Ge(B close
e$B$5$l$?$i!"%(%i!<$K$;$:$KC1$KH4$1$k!"$C$F$$$&$N$Oe(B
e$B$I$&$G$7$g$&$+e(B?

2010e$BG/e(B5e$B7ne(B8e$BF|e(B20:33 Tanaka A. [email protected]:

io/console e$B$r;H$C$F$_$?$N$G$9$,!“$A$g$C$H$&$^$/;H$($^$;$s!#e(B
IO#raw e$B$,e(B tty e$B$N>uBV$rI,$:85$K$b$I$9$s$G$9$,!”$=$l$,$A$g$C$H:$$j$^$9!#e(B

IO#raw e$B$G!“%V%m%C%/Fb$Ge(B close e$B$5$l$?$i!”%(%i!<$K$;$:$KC1$KH4$1$k!"$C$F$$$&$N$Oe(B
e$B$I$&$G$7$g$&$+e(B?

NEWS e$B$Ke(B

* IO#raw
* IO#raw {|io| }

e$B$H:$C$F$$$k$N$K5$$,$D$$$F$7$^$C$?$N$G$9$,!"e(B
e$B$b$7$+$7$F!"e(BIO#raw
e$B$K%V%m%C%/$rM?$($J$$$H%(%i!<$K$J$k$N$O0U?^$5$l$6$k5sF0e(B
e$B$J$s$G$7$g$&$+e(B?

% ./ruby -rpty -rio/console -e ’
m, s = PTY.open
s.raw

-e:3:in raw': no block given (LocalJumpError) from -e:3:in

2010e$BG/e(B5e$B7ne(B8e$BF|e(B20:59 Tanaka A. [email protected]:

NEWS e$B$Ke(B

  • IO#raw
  • IO#raw {|io| }

e$B$H:$C$F$$$k$N$K5$$,$D$$$F$7$^$C$?$N$G$9$,!"e(B
e$B$b$7$+$7$F!"e(BIO#raw e$B$K%V%m%C%/$rM?$($J$$$H%(%i!<$K$J$k$N$O0U?^$5$l$6$k5sF0e(B
e$B$J$s$G$7$g$&$+e(B?

e$B%V%m%C%/L5$7$N$,e(B NEWS e$B$+$i>C$($F!“e(BIO#raw {|io| }
e$B$OFbIt$Ge(B dup e$B$7$F3N<B$Ke(B
e$B>uBV$rLa$9$h$&$K$J$C$?$h$&$G$9$,!”$3$l$O:$$j$^$9!#e(B

e$BNc$K$"$2$?e(B PTY e$B$NMQK!$@$H!"La$7$?$/$J$$$s$G$9!#e(B

e$B$=$7$F!“?F%W%m%;%9$G$O!“e(BPTY e$B$Ne(B slave tty e$B$re(B open
e$B$7$F$*$-$?$/$”$j$^$;$s!#e(B
e$B$b$7!“e(Bopen e$B$7$?$^$^$@$H!”?F%W%m%;%9$,e(B master tty
e$B$+$iFI$_=P$7$Fe(B
EOF e$B$,8!CN$G$-$J$$$+$i$G$9!#e(B
(EOF e$B$8$c$J$/$F$J$K$+%(%i!<$K$J$k$+$b$7$l$^$;$s$,e(B)
e$B$3$l$,e(B IO#raw e$B$,N”$Ke(B fd
e$B$r1#$7;}$C$F$$$i$l$k$H!"$&$^$/$$$-$^$;$s!#e(B

e$B$=$s$J$o$1$G!“e(Bslave tty e$B$r?F%W%m%;%9$G$Oe(B close
e$B$7!”$+$D!“e(B
e$BC<Kv$O;R%W%m%;%9$+$i$N$?$a$Ke(B raw e$B$N$^$^$K$9$k!“e(B
e$B$H$$$&$N$,IT2DG=$J5$$,$9$k$s$G$9$,!”$J$K$+J}K!$O$”$j$^$9$+e(B?

2010e$BG/e(B5e$B7ne(B8e$BF|e(B23:24 Tanaka A. [email protected]:

e$B%V%m%C%/L5$7$N$,e(B NEWS e$B$+$i>C$($F!“e(BIO#raw {|io| } e$B$OFbIt$Ge(B dup e$B$7$F3N<B$Ke(B
e$B>uBV$rLa$9$h$&$K$J$C$?$h$&$G$9$,!”$3$l$O:$$j$^$9!#e(B

e$BNc$K$"$2$?e(B PTY e$B$NMQK!$@$H!"La$7$?$/$J$$$s$G$9!#e(B

e$B$=$s$J$o$1$G!“e(Bslave tty e$B$r?F%W%m%;%9$G$Oe(B close e$B$7!”$+$D!“e(B
e$BC<Kv$O;R%W%m%;%9$+$i$N$?$a$Ke(B raw e$B$N$^$^$K$9$k!“e(B
e$B$H$$$&$N$,IT2DG=$J5$$,$9$k$s$G$9$,!”$J$K$+J}K!$O$”$j$^$9$+e(B?

e$B8=>u$@$H>e5-$,<B8=$G$-$J$/$F:$$k$N$G0J2<$N$h$&$K$7$?$$$s$G$9$,$I$&$G$7$g$&$+!#e(B

e$B$3$&$G$"$l$P!“e(BIO#raw e$B$N%V%m%C%/Fb$Ge(B close e$B$9$k$H!“e(Btty
e$B$N>uBV$,La$i$5$J$$$3$H$,e(B
e$B<B8=$G$-!”$^$?!“N”$Ge(B fd e$B$,1#$l$FJ]B8$5$l$k$3$H$b$”$j$^$;$s!#e(B

Index: ext/io/console/console.c

— ext/io/console/console.c (revision 27700)
+++ ext/io/console/console.c (working copy)
@@ -173,23 +173,6 @@

#define FD_PER_IO 2

-#if defined HAVE_DUP3
-#define dup_private(fd) dup3((fd), -1, O_CLOEXEC)
-#elif defined F_DUPFD_CLOEXEC
-#define dup_private(fd) fcntl((fd), F_DUPFD_CLOEXEC)
-#elif defined O_CLOEXEC
-static inline int
-dup_private(int fd)
-{

  • fd = dup(fd);
  • if (fd != -1) fcntl(fd, F_SETFD, O_CLOEXEC);
  • return fd;
    -}
    -#define dup_private(fd) dup_private(fd)
    -#else
    -#define dup_private(fd) dup(fd)
    -#endif

static VALUE
ttymode(VALUE io, VALUE (*func)(VALUE), void (*setter)(conmode *))
{
@@ -197,7 +180,6 @@
int status = -1;
int error = 0;
int fd[FD_PER_IO];

  • int tmpfd, dupped = 0;
    conmode t[FD_PER_IO];
    VALUE result = Qnil;

@@ -205,10 +187,6 @@
fd[0] = GetReadFD(fptr);
if (fd[0] != -1) {
if (set_ttymode(fd[0], t+0, setter)) {

  •  if ((tmpfd = dup_private(fd[0])) != -1) {
    
  • fd[0] = tmpfd;
  • dupped |= 1 << 0;
  •  }
     status = 0;
    
    }
    else {
    @@ -219,10 +197,6 @@
    fd[1] = GetWriteFD(fptr);
    if (fd[1] != -1 && fd[1] != fd[0]) {
    if (set_ttymode(fd[1], t+1, setter)) {
  •  if ((tmpfd = dup_private(fd[1])) != -1) {
    
  • fd[1] = tmpfd;
  • dupped |= 1 << 1;
  •  }
     status = 0;
    
    }
    else {
    @@ -233,19 +207,20 @@
    if (status == 0) {
    result = rb_protect(func, io, &status);
    }
  • if (fd[0] != -1) {
  • if (!setattr(fd[0], t+0)) {
  •  error = errno;
    
  •  status = -1;
    
  • }
  • if (dupped & (1 << 0)) close(fd[0]);
  • }
  • if (fd[1] != -1 && fd[1] != fd[0]) {
  • if (!setattr(fd[1], t+1)) {
  •  error = errno;
    
  •  status = -1;
    
  • }
  • if (dupped & (1 << 1)) close(fd[1]);
  • if (0 <= RFILE(io)->fptr->fd) {
  •    GetOpenFile(io, fptr);
    
  •    if (fd[0] != -1 && fd[0] == GetReadFD(fptr)) {
    
  •        if (!setattr(fd[0], t+0)) {
    
  •            error = errno;
    
  •            status = -1;
    
  •        }
    
  •    }
    
  •    if (fd[1] != -1 && fd[1] != fd[0] && fd[1] == GetWriteFD(fptr)) 
    

{

  •        if (!setattr(fd[1], t+1)) {
    
  •            error = errno;
    
  •            status = -1;
    
  •        }
    
  •    }
    
    }
    if (status) {
    if (status == -1) {
    Index: ext/io/console/extconf.rb
    ===================================================================
    — ext/io/console/extconf.rb (revision 27700)
    +++ ext/io/console/extconf.rb (working copy)
    @@ -14,7 +14,6 @@
    end
    have_header(“sys/ioctl.h”)
    have_func(“rb_io_get_write_io”, “ruby/io.h”)
    -have_func(“dup3”, “unistd.h”)
    if ok
    create_makefile(“io/console”)
    end