From: nobu.nakada@... Date: 2001-06-29T21:59:24+09:00 Subject: [ruby-list:30417] Re: 1.6.4 と open3 なかだです。 At Fri, 29 Jun 2001 12:37:21 +0900, matz@ruby-lang.org (Yukihiro Matsumoto) wrote: > そうですね。open3はプロセスの終了を待つわけではありませんか > ら([ruby-list:30368]は特殊な例です)から、普通の方法では$?が > 取り出せないのは当たり前です。 そもそも非同期じゃないと意味ないですし、辻さんの例も、Ruby と sh で実はやってること違いますし。sh もバックグラウンドの exit code は捨ててるんですよね、やっぱり。 > * pipeに特異メソッドを付加 これは具体的にはどういうのを? exit code を得るためには popen3 内で wait することはできない し、忘れずに wait しなければゾンビが残るということで、両方を満 たすためには結局 finalizer を使うしかないはずでは。 内部クラスを作るのをやめて、ちょっとだけシンプルにしてみまし た。IO#pid= を追加すれば finalizer のところはもうちょっと簡単に なりますが。 Index: open3.rb =================================================================== RCS file: /cvs/ruby/src/ruby/lib/open3.rb,v retrieving revision 1.7 diff -u -2 -p -w -r1.7 open3.rb --- open3.rb 2001/05/16 09:05:54 1.7 +++ open3.rb 2001/06/29 10:40:46 @@ -9,4 +9,8 @@ module Open3 + def self.finalizer(pid) + proc {Process.waitpid(pid)} + end + #[stdin, stdout, stderr] = popen3(command); def popen3(*cmd) @@ -17,6 +21,4 @@ module Open3 pid = fork{ # child - fork{ - # grandchild pw[1].close STDIN.reopen(pw[0]) @@ -33,12 +35,15 @@ module Open3 exec(*cmd) } - exit! - } pw[0].close pr[1].close pe[1].close - Process.waitpid(pid) + wait = proc {|flag| Process.waitpid2(pid, flag).to_a.pop} + fin = Open3.finalizer(pid) pi = [pw[1], pr[0], pe[0]] + pi.each {|p| + class << p; self; end.module_eval {define_method(:wait, wait)} + ObjectSpace.define_finalizer(p, fin) + } if defined? yield begin @@ -46,4 +51,5 @@ module Open3 ensure pi.each{|p| p.close unless p.closed?} + begin Process.waitpid(pid) rescue Errno::ECHILD end end end -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦