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
