From: Tom Felker Date: 2003-05-28T07:29:02+09:00 Subject: Re: system calls On Tue, 2003-05-27 at 11:56, J.Hawkesworth wrote: > This is almost what you want, except that the exit code is wrong and I > don't > know how to fix it: > > require 'open3' > module Kernel > private > def really_cool_system(*args) > inp, out, err = Open3.popen3(*args) > ret1 = ret2 = nil > t1 = Thread.new do > inp.close > end > t2 = Thread.new do > ret1 = out.read > out.close > end > t3 = Thread.new do > ret2 = err.read > err.close > end > t1.join > t2.join > t3.join > return ret1, ret2, $? > end > end > > irb(main):024:0> really_cool_system("ls","/dev/null","/dev/foo") > => ["/dev/null\n", "ls: /dev/foo: No such file or directory\n", 65280] > > Regards, > > Brian. Yes, it's broken: true and false (which return 0 and 1 respectively) give the same value. The problem is in Open3.popen3. It forks twice, so the command it runs isn't Ruby's child. (I don't know why you'd want this.) That means $? is the return from the first fork, or something like that. There could be races also. To be used in a program with it's own children, you'd want to waitpid on the system call you spawned to get it's return value. I think Open3.popen3 should return [in, out, err, pid] so you could do this, but it doesn't, so you can't. Without waiting on the pid of your child, you can't reliably get the return value. -- Tom Felker They made a crude but listenable crystal radio out of a light bulb, a crayon, a square of toilet paper, and a rock. They say they'll have Linux running on it by next week.