> > probably we shouldn't get a crash, but a blackhole instead. > > Even a blackhole is wrong. There's no cycle so it ought to evaluate > successfully.
I didn't mean to suggest that a blackhole is correct, sorry for the confusion. No, obviously the code should just work. > > Fixing it so that the evaluation of x is actually continued is what > > we want, but I can't see an easy way to do that. > > I think GHC does the right thing (semantically) here. From memory, > GHC works like this: > > on entering thunk: turn it from a thunk into a blocking queue > (optimization: delay the transformation until context switch time) > > on entering a blocking queue: > if cyclic structure (i.e., already under evaluation by > same thread), > report blackhole. > otherwise, put this thread to sleep on the blocking queue. Delete the sentence "if cyclic structure..." and that's correct. If a thread goes to sleep on its own blocking queue, then it just deadlocks, and at some point later it will get a NonTermination exception when the RTS realises what it has done. > Based on this, what does GHC do here when a finalizer tries to > evaluate a thunk already being evaluated? The finalizer is put to > sleep until the main thread finishes evaluation of the thunk. Yup. > And what does GHC do if a call to unsafePerformIO hits a thunk already > under evaluation by the same thread? This is a blackhole (i.e., > deadlock). The thread throws the blackhole exception. Yup. > I think Hugs should report a blackhole in the unsafePerformIO case > (I believe it does already). Unless you try to exit and re-enter the RTS inside unsafePerformIO... (admittedly not very likely, but I bet you could make it fall over this way). > Hugs (and NHC, I believe) have no way to block finalizers once they > start executing. > > I think our only choice is to turn off blackholing, allow the shared > term to be evaluated twice over and hope that the two updates to the > thunk (one by finalizer and then one by the main thread) don't do any > harm. I don't know if this would work. Even if it does, it's not too > palatable because of the loss of sharing and the space leaks (that > blackholing normally fixes). Yes, I don't think this is a good solution. > > I suppose you could suspend either the finalizer or the main thread > > using the trick of saving its stack on the heap - is this > > implemented in Hugs? > > No - it is an STG-specific trick. Hugs is based on the G-machine. > > In Hugs, the state of a pure evaluation is stored on the C stack and > in the heap. We could try longjmp-ing out of the finalizer and hope > that the heap has a full and consistent record of the state but I'm > not overly confident that this would work. (Hmmm, longjmp-ing out is > what exception handlers do and we believe that those work....) > > > The only other solution I can think of is to delay finalizers until > > we get back up to the IO monad. > > and not inside an unsafePerformIO call. right. Cheers, Simon _______________________________________________ FFI mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/ffi