On 09/21/2013 10:37 PM, Jason E. Aten 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?

A task can't do that, but I'd suggest that perhaps rolling back global state doesn't need to be a requirement. Most computation in Rust is task-local.


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.

I must defer to your judgement on the issue of JIT rollback, because I don't understand it.


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!().

What is partial JIT compilation? As to the issue of arbitrary global memory modifying code, only unsafe Rust code will do that, and it's understood that when running unsafe code there is no safety net.


I'm certainly open to alternatives. How will that alternative address the rollback on fail!() problem?

All my thoughts on this subject are above. Tasks don't address all the problems you want to solve, but I suggest it may be ok not to solve them.

Regards,
Brian
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to