// Bah. Resending with the correct title, in hopes this gets threaded properly in the archives. Sorry for the duplication.
On Sat, Sep 21, 2013 at 10:37 PM, Jason E. Aten <[email protected]> wrote: > On Fri, 20 Sep 2013 Brian Anderson wrote: > >> On 09/19/2013 11:40 PM, Jason E. Aten wrote: > >> Perhaps the best thing is just to fork(2), so we get a new (OS level) > >> process that has copy-on-write (virtual) memory, and if the > >> compilation + run succeeds in the child, then have the child "take > >> over". Otherwise the child dies with an fail! + location message, and > >> we return to the parent exactly before the child was spawned. > > > > It seems a shame to be relying on process isolation instead of tasks. If > > I were to just imagine the architecture of a repl that used task > > isolation for crash recovery it might have one task for accepting input > > and another as a sandbox that maintains the repl state and executes > > commands in a loop. > > Yes, it seems a shame. It's even worse than a shame. It adds demands. > Using fork(2) demands a single-threaded runtime. Tasks don't require a > single threaded runtime. And tasks are more portable. Using fork(2) might > mean only supporting Linux or Linux & OSX at first. Windows support might > require cygwin's fork implementation, whereas tasks are everywhere. > > So I agree. It seems a shame. I want to do it with tasks only. I just > don't see how. How can we do this with tasks and get the desired rollback > on fail!()? > > I'll detail the problem a little. With only tasks, how do we rollback > changes to global state made by pre-compiled library functions that are > called from JIT-ed and run code? The task doesn't know what the arbitrary > code has done, so the task can't roll it back. Any functions in an > arbitrary C library, any unsafe Rust functions, and the JIT-compilation > itself will have updated global memory, the llvm module's symbols, etc. > Since we've fail!-ed at the end of an arbitrarily long sequence of code, > now we want that reverted all that cleanly and completely. How would a task > do that? > > I've been down that road for syntax errors before. I've implemented > rollback of everything that the LLVM-JIT added to an llvm module. It was a > pain, I had to track everything that the llvm jit-compiler did, so I could > roll back on syntax error. It was brittle, introducing a myraid of > undersirable code-interactions and logging to the current transaction code > intertwined with every llvm call. It was a pain, but it worked--for syntax > error rollback. > > But here we're not talking about *just* rolling back on syntax error. We > want to roll back not only the effects of a partial JIT-compilation, but to > also rollback after *running that code*. That code can call into > *arbitrary global memory modifying code*. All that we know is that an > arbitrary set of changes to the process image has ended in a fail!(). > > I'm certainly open to alternatives. How will that alternative address the > rollback on fail!() problem? > > Process isolation and using the copy-on-write/hardware (MMU) support for > copy-on-write virtual memory has been engineered for just this job. It fits > the situation like a glove. As a bonus: we get rollback of file handle > changes and all the other OS objects that are duplicated by fork(2). > > Jason >
_______________________________________________ Rust-dev mailing list [email protected] https://mail.mozilla.org/listinfo/rust-dev
