[GHC] #10793: Incorrect blocked on MVar detection

#10793: Incorrect blocked on MVar detection -------------------------------------+------------------------------------- Reporter: | Owner: simonmar NeilMitchell | Type: bug | Status: new Priority: normal | Milestone: Component: Runtime | Version: 7.10.1 System | Keywords: | Operating System: Windows Architecture: | Type of failure: None/Unknown Unknown/Multiple | Test Case: | Blocked By: Blocking: | Related Tickets: Differential Revisions: | -------------------------------------+------------------------------------- Given the code: {{{#!hs import Control.Concurrent main = do v <- newEmptyMVar forkFinally (putStrLn $ let x = x in x) (putMVar v) print =<< takeMVar v }}} The spawned thread should raise a {{{NonTermination}}} exception (assuming idle GC), then put it in the MVar {{{v}}}, which should cause the main thread to abort printing {{{Left <<loop>>}}}. However, in reality, the main thread aborts with {{{Exception: thread blocked indefinitely in an MVar operation}}}. My debugging shows that the spawned thread raises {{{NonTermination}}} and at the same time the main thread raises {{{BlockedIndefinitelyOnMVar}}}. Of course, the main thread is not really blocked on the exception, and after the finally bit runs, the MVar is filled. Adding tracing shows that the {{{putMVar}}} is called. Hypothesis is that the GC notices it can raise the non-termination exception, and then opportunistically excludes that thread from further GC scanning, and detects the MVar is unreferenced, raising the subsequent exception. Of course, given you can catch the exception, that isn't safe. Roman Leshchinskiy worries that in the wrong circumstances the MVar might really be being GC'd and thus could corrupt memory. This issue was detected while debugging an error in the Shake build system for GHC itself. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10793 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10793: Incorrect blocked on MVar detection -------------------------------------+------------------------------------- Reporter: NeilMitchell | Owner: simonmar Type: bug | Status: closed Priority: normal | Milestone: Component: Runtime System | Version: 7.10.1 Resolution: wontfix | Keywords: Operating System: Windows | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Revisions: -------------------------------------+------------------------------------- Changes (by simonmar): * status: new => closed * resolution: => wontfix Comment: This is working as intended. At the time the forked thread is deadlocked, the main thread is also deadlocked (the dependency between them is not visible to the GC). If you want to keep the main thread alive manually, you can do this: {{{ newStablePtr =<< myThreadId }}} from the main thread. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10793#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10793: Incorrect blocked on MVar detection -------------------------------------+------------------------------------- Reporter: NeilMitchell | Owner: simonmar Type: bug | Status: closed Priority: normal | Milestone: Component: Runtime System | Version: 7.10.1 Resolution: wontfix | Keywords: Operating System: Windows | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by NeilMitchell): I still don't understand, most likely because my understanding of what causes a BlockedIndefinitelyOnMVar exception is probably wrong. Is there a good link to the current semantics? And what actually triggers such an exception? Ditto for NonTermination. (And separately, should such pointers be added to the Exception docs?) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10793#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10793: Incorrect blocked on MVar detection -------------------------------------+------------------------------------- Reporter: NeilMitchell | Owner: simonmar Type: bug | Status: closed Priority: normal | Milestone: Component: Runtime System | Version: 7.10.1 Resolution: wontfix | Keywords: Operating System: Windows | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by simonmar): Well, thinking about it a bit more, in this case it would be possible to do something differently. We have * a main thread, blocked on an MVar * a child thread, in an infinite loop * the MVar, reachable from both threads. All of these things are unreachable from the roots, so we definitely can't make progress without throwing an exception. Normally we throw exceptions to all the deadlocked threads in this case, because it's the only deterministic thing we can do. (picking a thread randomly to receive the exception doesn't seem good). We could refine it slightly so that if there are both NonTermination exceptions and BlockedIndefinitelyOnMVar exceptions, we only throw the NonTermination exceptions. We know that waking up the BlockedIndefinitelyOnMVar threads can't unblock the NonTermination threads, but the reverse might be true. That wouldn't change the more common case of this, which is where both threads are blocked on MVars: {{{ main = do v <- newEmptyMVar v2 <- newEmptyMVar forkFinally (takeMVar v2) (putMVar v) print =<< takeMVar v }}} here we'd still get both exceptions at the same time. So I'm not sure how I feel about doing something different for `NonTermination`, possibly making the situation more complicated. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10793#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10793: Incorrect blocked on MVar detection -------------------------------------+------------------------------------- Reporter: NeilMitchell | Owner: simonmar Type: bug | Status: closed Priority: normal | Milestone: Component: Runtime System | Version: 7.10.1 Resolution: wontfix | Keywords: Operating System: Windows | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by NeilMitchell): * cc: simonmar (added) Comment: That all makes sense. From my perspective, NonTermination and BlockedIndefinitelyOnMVar are separate analysis passes (which as an implementation detail you have implemented in one go), and when viewed that way, having the first analysis raise the exceptions first seems quite reasonable. For info, I have a workaround in my case - catch the blocked exception, sleep for a second, then retry and see if the MVar is now filled. It's ugly (particularly the 1s sleep), but it works. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10793#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10793: Incorrect blocked on MVar detection -------------------------------------+------------------------------------- Reporter: NeilMitchell | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Runtime System | Version: 7.10.1 Resolution: | Keywords: Operating System: Windows | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by simonmar): * owner: simonmar => * status: closed => new * resolution: wontfix => -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10793#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10793: Incorrect blocked on MVar detection -------------------------------------+------------------------------------- Reporter: NeilMitchell | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Runtime System | Version: 7.10.1 Resolution: | Keywords: Operating System: Windows | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #10241 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by osa1): * cc: osa1 (added) * related: => #10241 -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10793#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10793: Incorrect blocked on MVar detection -------------------------------------+------------------------------------- Reporter: NeilMitchell | Owner: (none) Type: bug | Status: closed Priority: normal | Milestone: Component: Runtime System | Version: 7.10.1 Resolution: duplicate | Keywords: Operating System: Windows | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #10241 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by osa1): * status: new => closed * resolution: => duplicate Comment: Having read the ticket description again, I think this describes exactly the same problem as #10241 (multiple threads blocked, unblocking one unblocks others, but instead all of them are considered unblockable). Please re-open if you disagree. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10793#comment:7 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC