* process.c (check_exec_fds): resolve cascaded child fd reference.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@20511 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
2bb4ca64f9
commit
a112ec787a
@ -1,3 +1,7 @@
|
|||||||
|
Thu Dec 4 19:16:28 2008 Tanaka Akira <akr@fsij.org>
|
||||||
|
|
||||||
|
* process.c (check_exec_fds): resolve cascaded child fd reference.
|
||||||
|
|
||||||
Thu Dec 4 16:58:12 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
|
Thu Dec 4 16:58:12 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||||
|
|
||||||
* lib/rubygems/validator.rb (Gem#remove_leading_dot_dir): make
|
* lib/rubygems/validator.rb (Gem#remove_leading_dot_dir): make
|
||||||
|
38
process.c
38
process.c
@ -1516,7 +1516,12 @@ check_exec_fds(VALUE options)
|
|||||||
if (RTEST(rb_hash_lookup(h, INT2FIX(fd)))) {
|
if (RTEST(rb_hash_lookup(h, INT2FIX(fd)))) {
|
||||||
rb_raise(rb_eArgError, "fd %d specified twice", fd);
|
rb_raise(rb_eArgError, "fd %d specified twice", fd);
|
||||||
}
|
}
|
||||||
rb_hash_aset(h, INT2FIX(fd), INT2FIX(index));
|
if (index == EXEC_OPTION_OPEN || index == EXEC_OPTION_DUP2)
|
||||||
|
rb_hash_aset(h, INT2FIX(fd), Qtrue);
|
||||||
|
else if (index == EXEC_OPTION_DUP2_CHILD)
|
||||||
|
rb_hash_aset(h, INT2FIX(fd), RARRAY_PTR(elt)[1]);
|
||||||
|
else /* index == EXEC_OPTION_CLOSE */
|
||||||
|
rb_hash_aset(h, INT2FIX(fd), INT2FIX(-1));
|
||||||
if (maxhint < fd)
|
if (maxhint < fd)
|
||||||
maxhint = fd;
|
maxhint = fd;
|
||||||
if (index == EXEC_OPTION_DUP2 || index == EXEC_OPTION_DUP2_CHILD) {
|
if (index == EXEC_OPTION_DUP2 || index == EXEC_OPTION_DUP2_CHILD) {
|
||||||
@ -1527,20 +1532,33 @@ check_exec_fds(VALUE options)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* support cascaded mapping in future?
|
|
||||||
* fd1 => [:child, fd2],
|
|
||||||
* fd2 => [:child, fd3],
|
|
||||||
* fd3 => "/dev/null"
|
|
||||||
*/
|
|
||||||
ary = rb_ary_entry(options, EXEC_OPTION_DUP2_CHILD);
|
ary = rb_ary_entry(options, EXEC_OPTION_DUP2_CHILD);
|
||||||
if (!NIL_P(ary)) {
|
if (!NIL_P(ary)) {
|
||||||
for (i = 0; i < RARRAY_LEN(ary); i++) {
|
for (i = 0; i < RARRAY_LEN(ary); i++) {
|
||||||
VALUE elt = RARRAY_PTR(ary)[i];
|
VALUE elt = RARRAY_PTR(ary)[i];
|
||||||
|
int newfd = FIX2INT(RARRAY_PTR(elt)[0]);
|
||||||
int oldfd = FIX2INT(RARRAY_PTR(elt)[1]);
|
int oldfd = FIX2INT(RARRAY_PTR(elt)[1]);
|
||||||
VALUE vindex = rb_hash_lookup(h, INT2FIX(oldfd));
|
int lastfd = oldfd;
|
||||||
if (vindex != INT2FIX(EXEC_OPTION_DUP2) &&
|
VALUE val = rb_hash_lookup(h, INT2FIX(lastfd));
|
||||||
vindex != INT2FIX(EXEC_OPTION_OPEN)) {
|
long depth = 0;
|
||||||
|
while (FIXNUM_P(val) && 0 <= FIX2INT(val)) {
|
||||||
|
lastfd = FIX2INT(val);
|
||||||
|
val = rb_hash_lookup(h, val);
|
||||||
|
if (RARRAY_LEN(ary) < depth)
|
||||||
|
rb_raise(rb_eArgError, "cyclic child fd redirection from %d", oldfd);
|
||||||
|
depth++;
|
||||||
|
}
|
||||||
|
if (val != Qtrue)
|
||||||
rb_raise(rb_eArgError, "child fd %d is not redirected", oldfd);
|
rb_raise(rb_eArgError, "child fd %d is not redirected", oldfd);
|
||||||
|
if (oldfd != lastfd) {
|
||||||
|
VALUE val2;
|
||||||
|
rb_ary_store(elt, 1, INT2FIX(lastfd));
|
||||||
|
rb_hash_aset(h, INT2FIX(newfd), INT2FIX(lastfd));
|
||||||
|
val = INT2FIX(oldfd);
|
||||||
|
while (FIXNUM_P(val2 = rb_hash_lookup(h, val))) {
|
||||||
|
rb_hash_aset(h, val, INT2FIX(lastfd));
|
||||||
|
val = val2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2941,6 +2959,8 @@ rb_f_system(int argc, VALUE *argv)
|
|||||||
* pid = spawn(command, STDOUT=>["log", "w"], STDERR=>[:child, STDOUT])
|
* pid = spawn(command, STDOUT=>["log", "w"], STDERR=>[:child, STDOUT])
|
||||||
*
|
*
|
||||||
* [:child, STDOUT] can be used to merge STDERR into STDOUT in IO.popen.
|
* [:child, STDOUT] can be used to merge STDERR into STDOUT in IO.popen.
|
||||||
|
* In this case, IO.popen redirects STDOUT to a pipe in the child process
|
||||||
|
* and [:child, STDOUT] refers the redirected STDOUT.
|
||||||
*
|
*
|
||||||
* io = IO.popen(["sh", "-c", "echo out; echo err >&2", STDERR=>[:child, STDOUT]])
|
* io = IO.popen(["sh", "-c", "echo out; echo err >&2", STDERR=>[:child, STDOUT]])
|
||||||
* p io.read #=> "out\nerr\n"
|
* p io.read #=> "out\nerr\n"
|
||||||
|
@ -417,21 +417,30 @@ class TestProcess < Test::Unit::TestCase
|
|||||||
|
|
||||||
def test_execopts_redirect_dup2_child
|
def test_execopts_redirect_dup2_child
|
||||||
with_tmpchdir {|d|
|
with_tmpchdir {|d|
|
||||||
Process.wait spawn(RUBY, "-e", "STDERR.print 'err'; STDOUT.print 'out'", STDOUT=>"out", STDERR=>[:child, STDOUT])
|
Process.wait spawn(RUBY, "-e", "STDERR.print 'err'; STDOUT.print 'out'",
|
||||||
|
STDOUT=>"out", STDERR=>[:child, STDOUT])
|
||||||
assert_equal("errout", File.read("out"))
|
assert_equal("errout", File.read("out"))
|
||||||
Process.wait spawn(RUBY, "-e", "STDERR.print 'err'; STDOUT.print 'out'", STDERR=>"out", STDOUT=>[:child, STDERR])
|
|
||||||
|
Process.wait spawn(RUBY, "-e", "STDERR.print 'err'; STDOUT.print 'out'",
|
||||||
|
STDERR=>"out", STDOUT=>[:child, STDERR])
|
||||||
|
assert_equal("errout", File.read("out"))
|
||||||
|
|
||||||
|
Process.wait spawn(RUBY, "-e", "STDERR.print 'err'; STDOUT.print 'out'",
|
||||||
|
STDOUT=>"out",
|
||||||
|
STDERR=>[:child, 3],
|
||||||
|
3=>[:child, 4],
|
||||||
|
4=>[:child, STDOUT]
|
||||||
|
)
|
||||||
assert_equal("errout", File.read("out"))
|
assert_equal("errout", File.read("out"))
|
||||||
|
|
||||||
IO.popen([RUBY, "-e", "STDERR.print 'err'; STDOUT.print 'out'", STDERR=>[:child, STDOUT]]) {|io|
|
IO.popen([RUBY, "-e", "STDERR.print 'err'; STDOUT.print 'out'", STDERR=>[:child, STDOUT]]) {|io|
|
||||||
assert_equal("errout", io.read)
|
assert_equal("errout", io.read)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_raise(ArgumentError) {
|
assert_raise(ArgumentError) { Process.wait spawn(*TRUECOMMAND, STDOUT=>[:child, STDOUT]) }
|
||||||
Process.wait spawn(*TRUECOMMAND, STDOUT=>[:child, STDOUT])
|
assert_raise(ArgumentError) { Process.wait spawn(*TRUECOMMAND, 3=>[:child, 4], 4=>[:child, 3]) }
|
||||||
}
|
assert_raise(ArgumentError) { Process.wait spawn(*TRUECOMMAND, 3=>[:child, 4], 4=>[:child, 5], 5=>[:child, 3]) }
|
||||||
assert_raise(ArgumentError) {
|
assert_raise(ArgumentError) { Process.wait spawn(*TRUECOMMAND, STDOUT=>[:child, 3]) }
|
||||||
Process.wait spawn(*TRUECOMMAND, STDOUT=>[:child, 3])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user