[前][次][番号順一覧][スレッド一覧]

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

[前][次][番号順一覧][スレッド一覧]