On Wed, May 14, 2003 at 08:38:44AM +0900, Simon Strandgaard wrote:
> > No, because it cannot work. If I write
> > 
> >      s = ""
> >      $stdout = StringIO.new(s)
> >      pid = fork do
> >        exec("ls *.txt")
> >      end
> >      Process.wait(pid)
> > 
> > how are you going to modify fork or exec so that it captures the output of
> > 'ls' into the StringIO object created earlier?
> 
> I luckyly forgot all about this senario... I you can forgive me :-)
> 
> StringIO has no filedescriptor that fork() can parse down to the child.
> So we must create such filedescriptor.
> 
> A pipe and a receiver thread in the parent process should do it. 
> Some semaphore protection is probably necessary, But I don't have enough
> insight into the core of ruby, so I cannot tell where semaphore protection should
> go.  I think this is possible.

So I think you're saying you want Kernel#fork to do the following:
 - create a pipe
 - fork
 - in the child, dup2 the writer end to stdout/stderr then continue as
   normal
 - in the parent, start a new Ruby thread which takes data from the reader
   end of this pipe and writes it to $stdout (or $defout)

and make sure the Ruby IO system is thread-safe such that this child thread
can write to the StringIO object at the same time as the parent reads from
it (it may already be OK to do that). The thread dies when the pipe is
closed.

OK, now fix the following one-line Ruby program which you call from C++:

      exec("ls /tmp")

Note that right now it will not only write to Unix stdout, it will cause
your entire C++ program to exit.

Brian.