
On 14/08/10 02:30, Lennart Augustsson wrote:
So it's a bug in the garbage collector. It's closing a handle that clearly is still reachable, otherwise this would not have happened.
The handle is in fact not reachable from the roots, because the thread that points to it is also not reachable. More about it in this ticket: http://hackage.haskell.org/trac/ghc/ticket/2161 Some rationale from that ticket: "You may argue that a reference from a thread, even an unreachable one, should keep a ForeignPtr alive. But it's equally valid to argue the reverse: a reference from a finalizer should keep a thread alive - you don't want a thread to be considered deadlocked if it can be unblocked by a finalizer. We can't have both, because then a cycle between a finalizer and a thread would never be collected even when both were unreachable." So while we can flip this decision, it would have other undesirable consequences. I suppose I don't really have a good handle on how often you want one behaviour vs. the other - feedback welcome. Either way the GC has to do two extra phases after tracing from the roots: trace from the finalizers and then the unreachable threads, or vice versa. Cheers, Simon
On Fri, Aug 13, 2010 at 10:53 AM, Simon Marlow
wrote: On 12/08/2010 21:59, Yitzchak Gale wrote:
Wei Hu wrote:
nonTermination _ = blackhole where blackhole = blackhole
My original example was actually:
process :: String -> String process = let x = x in x
Ah yes, that works too. But other similar versions don't, like this one:
process :: String -> String process _ = let x = x in x
Hence why I added the "tail" in my version.
So what happens is this:
- the recursive definition causes the main thread to block on itself (known as a "black hole")
- the program is deadlocked (no threads to run), so the runtime invokes the GC to see if any threads are unreachable
- the GC finds that (a) the main thread is unreachable and blocked on a blackhole, so it gets a NonTermination exception (b) the Handle is unreachable, so its finalizer is started
- the finalizer runs first, and closes the Handle
- the main thread runs next, and the exception handler for writeFile tries to close the Handle, which has already been finalized
Really hClose shouldn't complain about a finalized handle, I'll see if I can fix that.
Cheers, Simon _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe