ruby-changes:2486
From: ko1@a...
Date: 20 Nov 2007 12:17:12 +0900
Subject: [ruby-changes:2486] akr - Ruby:r13977 (trunk): * include/ruby/io.h (rb_io_t): add tied_io_for_writing member.
akr 2007-11-20 12:16:53 +0900 (Tue, 20 Nov 2007) New Revision: 13977 Modified files: trunk/ChangeLog trunk/common.mk trunk/gc.c trunk/include/ruby/io.h trunk/io.c Log: * include/ruby/io.h (rb_io_t): add tied_io_for_writing member. * io.c: use tied_io_for_writing for duplex popen. * gc.c: mark tied_io_for_writing. * common.mk: gc.o depends io.h. [ruby-dev:32205] http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ChangeLog?r1=13977&r2=13976 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/io.c?r1=13977&r2=13976 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/gc.c?r1=13977&r2=13976 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/include/ruby/io.h?r1=13977&r2=13976 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/common.mk?r1=13977&r2=13976 Index: include/ruby/io.h =================================================================== --- include/ruby/io.h (revision 13976) +++ include/ruby/io.h (revision 13977) @@ -45,6 +45,7 @@ int rbuf_off; int rbuf_len; int rbuf_capa; + VALUE tied_io_for_writing; rb_encoding *enc; } rb_io_t; @@ -88,6 +89,7 @@ fp->rbuf_off = 0;\ fp->rbuf_len = 0;\ fp->rbuf_capa = 0;\ + fp->tied_io_for_writing = 0;\ } while (0) FILE *rb_io_stdio_file(rb_io_t *fptr); Index: ChangeLog =================================================================== --- ChangeLog (revision 13976) +++ ChangeLog (revision 13977) @@ -1,3 +1,15 @@ +Tue Nov 20 12:12:04 2007 Tanaka Akira <akr@f...> + + * include/ruby/io.h (rb_io_t): add tied_io_for_writing member. + + * io.c: use tied_io_for_writing for duplex popen. + + * gc.c: mark tied_io_for_writing. + + * common.mk: gc.o depends io.h. + + [ruby-dev:32205] + Tue Nov 20 11:59:33 2007 Tanaka Akira <akr@f...> * test/drb/test_drb.rb: rename TestRubyYield to TestDRbRubyYield to Index: io.c =================================================================== --- io.c (revision 13976) +++ io.c (revision 13977) @@ -158,6 +158,8 @@ #define open(file_spec, flags, mode) open(file_spec, flags, mode, "rfm=stmlf") #endif +#define GetWriteIO(io) rb_io_get_write_io(io) + #define READ_DATA_PENDING(fptr) ((fptr)->rbuf_len) #define READ_DATA_PENDING_COUNT(fptr) ((fptr)->rbuf_len) #define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf+(fptr)->rbuf_off) @@ -246,6 +248,17 @@ return rb_check_convert_type(io, T_FILE, "IO", "to_io"); } +VALUE +rb_io_get_write_io(VALUE io) +{ + VALUE write_io; + write_io = RFILE(io)->fptr->tied_io_for_writing; + if (write_io) { + return write_io; + } + return io; +} + /* * call-seq: * IO.try_convert(obj) -> io or nil @@ -676,6 +689,7 @@ VALUE tmp; rb_secure(4); + io = GetWriteIO(io); str = rb_obj_as_string(str); tmp = rb_io_check_io(io); if (NIL_P(tmp)) { @@ -748,6 +762,7 @@ return rb_funcall(io, id_flush, 0); } + io = GetWriteIO(io); GetOpenFile(io, fptr); if (fptr->mode & FMODE_WRITABLE) { @@ -982,6 +997,7 @@ { rb_io_t *fptr; + io = GetWriteIO(io); GetOpenFile(io, fptr); return (fptr->mode & FMODE_SYNC) ? Qtrue : Qfalse; } @@ -1006,6 +1022,7 @@ { rb_io_t *fptr; + io = GetWriteIO(io); GetOpenFile(io, fptr); if (RTEST(mode)) { fptr->mode |= FMODE_SYNC; @@ -1034,6 +1051,7 @@ #ifdef HAVE_FSYNC rb_io_t *fptr; + io = GetWriteIO(io); GetOpenFile(io, fptr); io_fflush(fptr); @@ -1464,6 +1482,7 @@ if (TYPE(str) != T_STRING) str = rb_obj_as_string(str); + io = GetWriteIO(io); GetOpenFile(io, fptr); rb_io_check_writable(fptr); @@ -2348,7 +2367,17 @@ { rb_io_t *fptr; int fd; + VALUE write_io; + rb_io_t *write_fptr; + write_io = GetWriteIO(io); + if (io != write_io) { + write_fptr = RFILE(write_io)->fptr; + if (write_fptr && 0 <= write_fptr->fd) { + rb_io_fptr_cleanup(write_fptr, Qtrue); + } + } + fptr = RFILE(io)->fptr; if (!fptr) return Qnil; if (fptr->fd < 0) return Qnil; @@ -2425,7 +2454,17 @@ rb_io_closed(VALUE io) { rb_io_t *fptr; + VALUE write_io; + rb_io_t *write_fptr; + write_io = GetWriteIO(io); + if (io != write_io) { + write_fptr = RFILE(write_io)->fptr; + if (write_fptr && 0 <= write_fptr->fd) { + return Qfalse; + } + } + fptr = RFILE(io)->fptr; rb_io_check_initialized(fptr); return 0 <= fptr->fd ? Qfalse : Qtrue; @@ -2453,6 +2492,7 @@ rb_io_close_read(VALUE io) { rb_io_t *fptr; + VALUE write_io; if (rb_safe_level() >= 4 && !OBJ_TAINTED(io)) { rb_raise(rb_eSecurityError, "Insecure: can't close"); @@ -2469,6 +2509,13 @@ return rb_io_close(io); return Qnil; } + + write_io = GetWriteIO(io); + if (io != write_io) { + fptr_finalize(fptr, Qfalse); + return Qnil; + } + if (fptr->mode & FMODE_WRITABLE) { rb_raise(rb_eIOError, "closing non-duplex IO for reading"); } @@ -2502,6 +2549,7 @@ if (rb_safe_level() >= 4 && !OBJ_TAINTED(io)) { rb_raise(rb_eSecurityError, "Insecure: can't close"); } + io = GetWriteIO(io); GetOpenFile(io, fptr); if (is_socket(fptr->fd, fptr->path)) { #ifndef SHUT_WR @@ -2582,6 +2630,7 @@ if (TYPE(str) != T_STRING) str = rb_obj_as_string(str); + io = GetWriteIO(io); GetOpenFile(io, fptr); rb_io_check_writable(fptr); @@ -2666,15 +2715,6 @@ return str; } -/* - * call-seq: - * ios.binmode => ios - * - * Puts <em>ios</em> into binary mode. This is useful only in - * MS-DOS/Windows environments. Once a stream is in binary mode, it - * cannot be reset to nonbinary mode. - */ - VALUE rb_io_binmode(VALUE io) { @@ -2693,6 +2733,30 @@ return io; } +/* + * call-seq: + * ios.binmode => ios + * + * Puts <em>ios</em> into binary mode. This is useful only in + * MS-DOS/Windows environments. Once a stream is in binary mode, it + * cannot be reset to nonbinary mode. + */ + +static VALUE +rb_io_binmode_m(VALUE io) +{ +#if defined(_WIN32) || defined(DJGPP) || defined(__CYGWIN__) || defined(__human68k__) || defined(__EMX__) + VALUE write_io; + + rb_io_binmode(io); + + write_io = GetWriteIO(io); + if (write_io != io) + rb_io_binmode(write_io); +#endif + return io; +} + static const char* rb_io_flags_mode(int flags) { @@ -3078,17 +3142,23 @@ struct rb_exec_arg exec; int modef; int pair[2]; + int write_pair[2]; }; static void popen_redirect(struct popen_arg *p) { if ((p->modef & FMODE_READABLE) && (p->modef & FMODE_WRITABLE)) { + close(p->write_pair[1]); + if (p->write_pair[0] != 0) { + dup2(p->write_pair[0], 0); + close(p->write_pair[0]); + } close(p->pair[0]); - dup2(p->pair[1], 0); - dup2(p->pair[1], 1); - if (2 <= p->pair[1]) + if (p->pair[1] != 1) { + dup2(p->pair[1], 1); close(p->pair[1]); + } } else if (p->modef & FMODE_READABLE) { close(p->pair[0]); @@ -3132,6 +3202,8 @@ int pid = 0; rb_io_t *fptr; VALUE port; + rb_io_t *write_fptr; + VALUE write_port; #if defined(HAVE_FORK) int status; struct popen_arg arg; @@ -3141,17 +3213,24 @@ #endif FILE *fp = 0; int fd = -1; + int write_fd = -1; #if defined(HAVE_FORK) arg.modef = modef; arg.pair[0] = arg.pair[1] = -1; + arg.write_pair[0] = arg.write_pair[1] = -1; switch (modef & (FMODE_READABLE|FMODE_WRITABLE)) { -#if defined(HAVE_SOCKETPAIR) case FMODE_READABLE|FMODE_WRITABLE: - if (socketpair(AF_UNIX, SOCK_STREAM, 0, arg.pair) < 0) + if (pipe(arg.write_pair) < 0) rb_sys_fail(cmd); + if (pipe(arg.pair) < 0) { + int e = errno; + close(arg.write_pair[0]); + close(arg.write_pair[1]); + errno = e; + rb_sys_fail(cmd); + } break; -#endif case FMODE_READABLE: if (pipe(arg.pair) < 0) rb_sys_fail(cmd); @@ -3187,12 +3266,18 @@ int e = errno; close(arg.pair[0]); close(arg.pair[1]); + if ((modef & (FMODE_READABLE|FMODE_WRITABLE)) == (FMODE_READABLE|FMODE_WRITABLE)) { + close(arg.write_pair[0]); + close(arg.write_pair[1]); + } errno = e; rb_sys_fail(cmd); } if ((modef & FMODE_READABLE) && (modef & FMODE_WRITABLE)) { close(arg.pair[1]); fd = arg.pair[0]; + close(arg.write_pair[0]); + write_fd = arg.write_pair[1]; } else if (modef & FMODE_READABLE) { close(arg.pair[1]); @@ -3245,6 +3330,16 @@ fptr->mode = modef | FMODE_SYNC|FMODE_DUPLEX; fptr->pid = pid; + if (0 <= write_fd) { + write_port = io_alloc(rb_cIO); + MakeOpenFile(write_port, write_fptr); + write_fptr->fd = write_fd; + write_fptr->mode = (modef & ~FMODE_READABLE)| FMODE_SYNC|FMODE_DUPLEX; + fptr->mode &= ~FMODE_WRITABLE; + fptr->tied_io_for_writing = write_port; + rb_ivar_set(port, rb_intern("@tied_io_for_writing"), write_port); + } + #if defined (__CYGWIN__) || !defined(HAVE_FORK) fptr->finalize = pipe_finalize; pipe_add_fptr(fptr); @@ -3770,6 +3865,7 @@ { rb_io_t *fptr, *orig; int fd; + VALUE write_io; io = rb_io_get_io(io); if (dest == io) return dest; @@ -3792,6 +3888,13 @@ rb_io_binmode(dest); } + write_io = GetWriteIO(io); + if (io != write_io) { + write_io = rb_obj_dup(write_io); + fptr->tied_io_for_writing = write_io; + rb_ivar_set(dest, rb_intern("@tied_io_for_writing"), write_io); + } + return dest; } @@ -4732,7 +4835,8 @@ if (!NIL_P(write)) { Check_Type(write, T_ARRAY); for (i=0; i<RARRAY_LEN(write); i++) { - GetOpenFile(rb_io_get_io(RARRAY_PTR(write)[i]), fptr); + VALUE write_io = GetWriteIO(rb_io_get_io(RARRAY_PTR(write)[i])); + GetOpenFile(write_io, fptr); rb_fd_set(fptr->fd, &fds[1]); if (max < fptr->fd) max = fptr->fd; } @@ -4744,9 +4848,16 @@ if (!NIL_P(except)) { Check_Type(except, T_ARRAY); for (i=0; i<RARRAY_LEN(except); i++) { - GetOpenFile(rb_io_get_io(RARRAY_PTR(except)[i]), fptr); + VALUE io = rb_io_get_io(RARRAY_PTR(except)[i]); + VALUE write_io = GetWriteIO(io); + GetOpenFile(io, fptr); rb_fd_set(fptr->fd, &fds[2]); if (max < fptr->fd) max = fptr->fd; + if (io != write_io) { + GetOpenFile(write_io, fptr); + rb_fd_set(fptr->fd, &fds[2]); + if (max < fptr->fd) max = fptr->fd; + } } ep = rb_fd_ptr(&fds[2]); } @@ -4771,10 +4882,11 @@ if (rp) { list = RARRAY_PTR(res)[0]; for (i=0; i< RARRAY_LEN(read); i++) { - GetOpenFile(rb_io_get_io(RARRAY_PTR(read)[i]), fptr); + VALUE io = rb_io_get_io(rb_ary_entry(read, i)); + GetOpenFile(io, fptr); if (rb_fd_isset(fptr->fd, &fds[0]) || rb_fd_isset(fptr->fd, &fds[3])) { - rb_ary_push(list, rb_ary_entry(read, i)); + rb_ary_push(list, io); } } } @@ -4782,9 +4894,11 @@ if (wp) { list = RARRAY_PTR(res)[1]; for (i=0; i< RARRAY_LEN(write); i++) { - GetOpenFile(rb_io_get_io(RARRAY_PTR(write)[i]), fptr); + VALUE io = rb_io_get_io(rb_ary_entry(write, i)); + VALUE write_io = GetWriteIO(io); + GetOpenFile(write_io, fptr); if (rb_fd_isset(fptr->fd, &fds[1])) { - rb_ary_push(list, rb_ary_entry(write, i)); + rb_ary_push(list, io); } } } @@ -4792,10 +4906,18 @@ if (ep) { list = RARRAY_PTR(res)[2]; for (i=0; i< RARRAY_LEN(except); i++) { - GetOpenFile(rb_io_get_io(RARRAY_PTR(except)[i]), fptr); + VALUE io = rb_io_get_io(rb_ary_entry(write, i)); + VALUE write_io = GetWriteIO(io); + GetOpenFile(io, fptr); if (rb_fd_isset(fptr->fd, &fds[2])) { - rb_ary_push(list, rb_ary_entry(except, i)); + rb_ary_push(list, io); } + else if (io != write_io) { + GetOpenFile(write_io, fptr); + if (rb_fd_isset(fptr->fd, &fds[2])) { + rb_ary_push(list, io); + } + } } } } @@ -5906,7 +6028,7 @@ rb_define_method(rb_cIO, "isatty", rb_io_isatty, 0); rb_define_method(rb_cIO, "tty?", rb_io_isatty, 0); - rb_define_method(rb_cIO, "binmode", rb_io_binmode, 0); + rb_define_method(rb_cIO, "binmode", rb_io_binmode_m, 0); rb_define_method(rb_cIO, "sysseek", rb_io_sysseek, -1); rb_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1); Index: common.mk =================================================================== --- common.mk (revision 13976) +++ common.mk (revision 13977) @@ -442,7 +442,7 @@ gc.$(OBJEXT): {$(VPATH)}gc.c {$(VPATH)}ruby.h {$(VPATH)}config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ {$(VPATH)}signal.h {$(VPATH)}st.h {$(VPATH)}node.h \ - {$(VPATH)}re.h {$(VPATH)}regex.h {$(VPATH)}oniguruma.h \ + {$(VPATH)}re.h {$(VPATH)}io.h {$(VPATH)}regex.h {$(VPATH)}oniguruma.h \ {$(VPATH)}vm_core.h {$(VPATH)}id.h {$(VPATH)}debug.h {$(VPATH)}vm_opts.h \ {$(VPATH)}thread_$(THREAD_MODEL).h hash.$(OBJEXT): {$(VPATH)}hash.c {$(VPATH)}ruby.h {$(VPATH)}config.h \ Index: gc.c =================================================================== --- gc.c (revision 13976) +++ gc.c (revision 13977) @@ -17,6 +17,7 @@ #include "ruby/st.h" #include "ruby/node.h" #include "ruby/re.h" +#include "ruby/io.h" #include "vm_core.h" #include "gc.h" #include <stdio.h> @@ -1080,6 +1081,9 @@ break; case T_FILE: + gc_mark(obj->as.file.fptr->tied_io_for_writing, lev); + break; + case T_REGEXP: case T_FLOAT: case T_BIGNUM: -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml