mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* 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] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13977 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
ee1029cb7f
commit
0d8ac93f58
5 changed files with 165 additions and 25 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
|||
Tue Nov 20 12:12:04 2007 Tanaka Akira <akr@fsij.org>
|
||||
|
||||
* 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@fsij.org>
|
||||
|
||||
* test/drb/test_drb.rb: rename TestRubyYield to TestDRbRubyYield to
|
||||
|
|
|
@ -442,7 +442,7 @@ file.$(OBJEXT): {$(VPATH)}file.c {$(VPATH)}ruby.h {$(VPATH)}config.h \
|
|||
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 \
|
||||
|
|
4
gc.c
4
gc.c
|
@ -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 @@ gc_mark_children(VALUE ptr, int lev)
|
|||
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:
|
||||
|
|
|
@ -45,6 +45,7 @@ typedef struct rb_io_t {
|
|||
int rbuf_off;
|
||||
int rbuf_len;
|
||||
int rbuf_capa;
|
||||
VALUE tied_io_for_writing;
|
||||
rb_encoding *enc;
|
||||
} rb_io_t;
|
||||
|
||||
|
@ -88,6 +89,7 @@ typedef struct rb_io_t {
|
|||
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);
|
||||
|
|
170
io.c
170
io.c
|
@ -158,6 +158,8 @@ static VALUE lineno = INT2FIX(0);
|
|||
#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 @@ rb_io_check_io(VALUE io)
|
|||
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 @@ io_write(VALUE io, VALUE str)
|
|||
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 @@ rb_io_flush(VALUE io)
|
|||
return rb_funcall(io, id_flush, 0);
|
||||
}
|
||||
|
||||
io = GetWriteIO(io);
|
||||
GetOpenFile(io, fptr);
|
||||
|
||||
if (fptr->mode & FMODE_WRITABLE) {
|
||||
|
@ -982,6 +997,7 @@ rb_io_sync(VALUE io)
|
|||
{
|
||||
rb_io_t *fptr;
|
||||
|
||||
io = GetWriteIO(io);
|
||||
GetOpenFile(io, fptr);
|
||||
return (fptr->mode & FMODE_SYNC) ? Qtrue : Qfalse;
|
||||
}
|
||||
|
@ -1006,6 +1022,7 @@ rb_io_set_sync(VALUE io, VALUE mode)
|
|||
{
|
||||
rb_io_t *fptr;
|
||||
|
||||
io = GetWriteIO(io);
|
||||
GetOpenFile(io, fptr);
|
||||
if (RTEST(mode)) {
|
||||
fptr->mode |= FMODE_SYNC;
|
||||
|
@ -1034,6 +1051,7 @@ rb_io_fsync(VALUE io)
|
|||
#ifdef HAVE_FSYNC
|
||||
rb_io_t *fptr;
|
||||
|
||||
io = GetWriteIO(io);
|
||||
GetOpenFile(io, fptr);
|
||||
|
||||
io_fflush(fptr);
|
||||
|
@ -1464,6 +1482,7 @@ rb_io_write_nonblock(VALUE io, VALUE str)
|
|||
if (TYPE(str) != T_STRING)
|
||||
str = rb_obj_as_string(str);
|
||||
|
||||
io = GetWriteIO(io);
|
||||
GetOpenFile(io, fptr);
|
||||
rb_io_check_writable(fptr);
|
||||
|
||||
|
@ -2348,6 +2367,16 @@ rb_io_close(VALUE io)
|
|||
{
|
||||
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;
|
||||
|
@ -2425,6 +2454,16 @@ static VALUE
|
|||
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);
|
||||
|
@ -2453,6 +2492,7 @@ static VALUE
|
|||
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 @@ rb_io_close_read(VALUE io)
|
|||
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 @@ rb_io_close_write(VALUE io)
|
|||
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 @@ rb_io_syswrite(VALUE io, VALUE str)
|
|||
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 @@ rb_io_sysread(int argc, VALUE *argv, VALUE io)
|
|||
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 @@ rb_io_binmode(VALUE io)
|
|||
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 popen_arg {
|
|||
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 @@ pipe_open(const char *cmd, int argc, VALUE *argv, const char *mode)
|
|||
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 @@ pipe_open(const char *cmd, int argc, VALUE *argv, const char *mode)
|
|||
#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 @@ pipe_open(const char *cmd, int argc, VALUE *argv, const char *mode)
|
|||
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 @@ pipe_open(const char *cmd, int argc, VALUE *argv, const char *mode)
|
|||
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_init_copy(VALUE dest, VALUE io)
|
|||
{
|
||||
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_init_copy(VALUE dest, VALUE io)
|
|||
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 @@ select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fd
|
|||
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 @@ select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fd
|
|||
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 @@ select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fd
|
|||
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 @@ select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fd
|
|||
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 @@ select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fd
|
|||
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 @@ Init_IO(void)
|
|||
|
||||
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);
|
||||
|
|
Loading…
Add table
Reference in a new issue