From: Simon Strandgaard <0bz63fz3m1qt3001@...> Date: 2003-05-13T09:48:53+09:00 Subject: Re: RCR for child execution On Tue, 13 May 2003 08:39:34 +0900, Brian Candler wrote: [snip top - continued from previous post] > But then you say that you want to do this without modifying existing Ruby > code. You can always replace 'system' and 'backtick' with your own versions > if you wish. But I still don't think it makes sense. mm.. I better state more exactly what "existing Ruby code" means here. This is NOT the core of ruby. I am working on a programmers-editor where the backend is ruby and the frontend is c++ (ruby embedded into c++). I want users of the editor to be able to use thier own favorite ruby snippets within the editor... *unmodified* ...they don't have to do popen or Open3 or other ackward things for executing their favorite scripts. All Ruby output should go to a text-buffer. http://prdownloads.sourceforge.net/metaeditor/aeditorlib-0.1.tar.gz?download Enough advertisement.. I hope you understand my rationale now ? > The environment in which a Unix program runs looks, at its simplest, like > this: > > MAIN > +---------------------------------+ > | | > | FD | > stdin -------> | 0 | > stdout<------- | 1 | > stderr<------- | 2 | > | | > | | > +---------------------------------+ > > It can ignore stdin/stdout/stderr of course - as it would if it were a GUI > program, say. > > Now, from this main program, you want to call a function, which happens to > be written in Ruby. > > It must be true that either: > > * This function makes no use of stdin/stdout/stderr at all. In that case > there is no problem, agreed? Agree: puts, print, p, printf, write.. OK > * This function *does* communicate on stdin/stdout/stderr. > > So I think you are saying in the second case you want to run it in a > 'sandbox', a simulated Unix environment where it gets its own private > stdin/stdout/stderr: Yes yes yes yes... We should have painted such diagram several days ago, then we could have avoided much of this confusion. > +---------------------------------+ > | | > | +-----------+ | > stdin -------> | 0 obj0-->| 0 Sandbox | | > stdout<------- | 1 obj1<--| 1 | | > stderr<------- | 2 obj2<--| 2 | | > | +-----------+ | > | | > +---------------------------------+ > > I think you are asking for the Ruby interpreter to be the sandbox itself, > and to trap every single possible case where output might be written to > stdout/stderr, and have it redirect to Ruby IO calls instead. Putting Ruby into a sandbox is what my RCR proposal is about. This is currently not possible.. therefore the RCR. > In the general > case, this is simply not possible whilst the Sandbox is in the same process > as you, because it shares fd0/1/2 with the the main program (because both > Ruby and C *are* part of the same program), and therefore the program has a > way to write to fd0/1/2. Not agree.. I think this *is* possible. Everytime Ruby spawns a child it should do like this: void system(command) { pid=fork(); if(pid != 0) { stdout = rb_stdout; /* what im asking for */ stderr = rb_stderr; /* what im asking for */ stdin = rb_stdin; /* what im asking for */ execv(command); } } OK.. again assignment to stdout is illegal. freopen should be used instead. Admitted.. I havn't yet tried reopen'ing stdout/stderr :-) > Rewriting 'system' and backtick would catch some cases, but certainly not > all. Agree.. A nicer solution is what we are looking for. > The only way to guarantee trapping of all output on fd 1 in the Sandbox into > some string object 'obj1' is to do it at the Unix API layer. This means > creating a new pipe and pass one end of it to the code running in the > Sandbox as fd 1. This then *forces* you to use a separate process, because > it must be possible for the Sandbox to be doing work and writing to one end > of the pipe whilst the main program is reading the other end of the pipe. > (You could also use native threads, but Ruby doesn't play safely with > threads) I run ruby in one semaphore protected thread.. no extra process. I have a thread in C++ which is flushing the pipe and stores it into a text-buffer. [snip summary] I will look at the summary later :-) -- Simon Strandgaard