On Fri, May 09, 2003 at 09:55:32AM +0900, Simon Strandgaard wrote: > Problem is almost solved, thanks for pointing me in the right direction. > > I have been experimenting a little with a pipe between 2 threads :-) > TODO: this has to be integrated into my embedding code. > This might have others interest. Is this planned as part of "Embedding Ruby in C++ tutorial"? If so, I hope you don't mind if I argue that it doesn't belong there. I had a bit of a think about this, and setting Ruby aside for the moment, why not consider the following question similar to your original one: If I write a subroutine (function) in C++, how can I wrap it so that any output it generates does not go to stdout, but is discarded or captured in a string? Now, I'm not a C++ programmer, but I imagine the answer goes something along the lines of: "change cout to point to a new object, so that cout << "foo" writes to this object rather than what cout normally points to". Or you could close fd 1 and fd 2 and reopen them pointing to /tmp/result or /dev/null. This is all fine so far. However there are a number of ways in which the subroutine could bypass this restriction if it chose to: (1) it explicitly opens /dev/stdout to a new fd, and writes to it (2) it explicitly write()s to fd 1 (3) it forks and execs a child, and the child writes to stdout (4) probably a load of other things (2) and (3) won't be an issue if you had reopened fd 1, because they will write to whatever you reopened it as (say /tmp/result, which you can read later) However none of this is a problem. A C++ subroutine, after all, is just a part of your main C++ program. If it explicitly writes to stdout or stderr, then so be it; and if you don't want it to do these things, then you code your subroutine so that it doesn't. If you need to do point (2), that is fork and exec a child, you can explicitly set up fd 1 and 2 for the child, e.g. as pipes which the parent process reads, before the exec. Now, the point I'm trying to make is, embedded Ruby is no different to a C++ subroutine. They are part of one and the same program. They are called from your main() function or elsewhere, do some work, and return. The C++ subroutine sits inside the same C++ execution environment as the main program, as does the embedded Ruby - they share the same memory space, file descriptors, and so on. Therefore the same thing applies for capturing output. If a C++ subroutine decides to fork off a child and needs to capture its output, it is the responsibility of the C++ subroutine itself to do that. The same would apply to embedded Ruby doing this sort of thing. Hence I do not believe that it is necessary or even desirable to try to set up some sort of 'sand box' execution environment for the Ruby interpreter, when it is *part of your program*. In fact it could be a positive disadvantage, because I for one would definitely want the ability for my Ruby code to report debug messages to stderr, in the same way as my C(++) code can. I cannot see any real-world application where such a sandbox is needed, because it probably just means that the logic is being done in the wrong place: if the Ruby part of your program needs to redirect any output it generates, or capture output of a child, then just do it in Ruby. Just to be clear, I think writing up a tutorial on this embedding is a really worthwhile thing to do, and I applaud you for doing so. But I think it's important not to make it seem like this sort of sandboxing is necessary, because it makes embedding Ruby look far harder than it actually is, and might put people off. Material for an appendix perhaps. One final point: you posted some code showing native threads communicating over a pipe. I think it's a very bad idea to encourage use of threads in embedded Ruby applications, because Ruby really does not play well with them. If you made sure that *all* Ruby calls occured in *one* thread it would probably work, but a safer rule (especially for a tutorial) is: just don't do it. You'll see recent postings to this list of people who have tried it, with good reason to do so, and have achieved little more than some spectacular crashes. So, if I needed to call some Ruby from C++ and have it as a totally separate entity which I communicated with down a pipe, then I would fork a new process. However this loses much of the benefit of embedding because the _only_ way you could communicate with it would be down the pipe... no direct method calls or rb_eval_string or whatever. Regards, Brian.