
Isaac Dupree wrote:
Bertram Felgenhauer wrote:
Now in fact, IO actions are indistinguishable from pure computations by the RTS, so this mechanism also makes IO actions resumable, in principle, if you can access the corresponding thunk somehow. Normally you can't - there is no reference to that thunk - but unsafePerformIO gives you that reference.
I wonder if other things break in the presence of resumable IO computations... the first thing that comes to mind is, inside a "block" or "unblock" (which have to initiate, take down and deal with all that infrastructure -- luckily you only use them inside a separate thread, a forkIO within the unsafePerformIO... Which admittedly makes things horribly confusing in its own way. Also does forkIO copy any state? it copies blocked status now, which the unamb-calling thread might have...). The state of the thread when entering the computation again, could be different than it was when the computation was first suspended, I'm guessing. (At least you need to be careful about what invariants you assume; I'm not yet sure if it's possible to be careful enough.)
There's one other bug in this area that we've known about for a while. In the comments in Exception.cmm: NB. there's a bug in here. If a thread is inside an unsafePerformIO, and inside blockAsyncExceptions# (there is an unblockAsyncExceptions_ret on the stack), and it is blocked in an interruptible operation, and it receives an exception, then the unsafePerformIO thunk will be updated with a stack object containing the unblockAsyncExceptions_ret frame. Later, when someone else evaluates this thunk, the blocked exception state is not restored. this probably isn't affecting reactive, but I thought I'd mention it. Cheers, Simon