[GHC] #10241: BlockedIndefinitelyOnMVar thrown to the thread which is not blocked indefinitely

GHC ghc-devs at haskell.org
Mon Apr 30 09:41:23 UTC 2018


#10241: BlockedIndefinitelyOnMVar thrown to the thread which is not blocked
indefinitely
-------------------------------------+-------------------------------------
        Reporter:  asukamirai        |                Owner:  simonmar
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Runtime System    |              Version:  7.8.3
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:  x86_64
 Type of failure:  Incorrect result  |  (amd64)
  at runtime                         |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------
Changes (by osa1):

 * cc: osa1 (added)


Comment:

 I've been recently reading the relevant code, and I think this is indeed a
 bug.

 Basically we raise an async `BlockedIndefinitelyOnMVar` when a thread is
 not reachable and blocked in an MVar operation.

 Reachability in this context means:

 - If a thread has work to do it's reachable (because it's in run queue of
 one of the capabilities)
 - If a thread is blocked in an MVar it's reachable iff the MVar is
 reachable

 Now suppose that thread_1 is blocked on mvar_1 and has a reference to
 mvar_2, and thread_2 is blocked on mvar_2, and both MVars become
 unreachable after a GC. This makes both thread_1 and thread_2 unreachable
 and we add them to the "thrads to resurrect" list. By the time we
 resurrect thread_1, mvar_2 becomes reachable, which makes thread_2
 reachable as well. But we already added thread_2 to the "threads to
 resurrect" list so we raise an exception in thread_2 as well.

 I think this is basically what's happening in this ticket.

 Why adding a delay fixes this? Because by the time the main thread is
 paused with the delay it's in the run queue of the capability because it
 has more work to do. So the delay makes the main thread reachable for a
 few more GC cycles, and `BlockedIndefinitelyOnMVar` is only raised on
 resurrected (unreachable) threads.

 I think fixing this may be easy; instead of resurrecting all unreachable
 threads at once, we resurrect one from the list, then continue with the
 scavenge loop. I'll try this once my tree builds.

-- 
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10241#comment:1>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list