BlockedIndefinitelyOnMVar exception

Neil Mitchell ndmitchell at gmail.com
Sun Jul 4 16:51:10 EDT 2010


>> http://hackage.haskell.org/trac/ghc/ticket/4154
>
> Yup, that's a bug.  Not clear if it's fixable.
>
>> http://hackage.haskell.org/trac/ghc/ticket/3527
>
> That too.  A very similar bug in fact, if there is a fix it will probably
> fix both of them.  The problem is that readChan holds a lock on the read end
> of the Chan, so neither isEmptyChan nor unGetChan can work when a reader is
> blocked.

I wrote my Chan around the abstraction:

data Chan a = Chan (MVar (Either [a] [MVar a]))

The Chan either has elements in it (Left), or has readers waiting for
elements (Right). To get the fairness properties on Chan you might
want to make these two lists Queue's, but I think the basic principle
still works. By using this abstraction my Chan was a lot simpler. With
this scheme implementing isEmpyChan or unGetChan would both work
nicely. My Chan was not designed for performance. (In truth I replaced
the Left with IntMap a, and inserted elements with a randomly chosen
key, but the basic idea is the same.)

>> own Chan implementation worked. My Chan had different properties (it
>> queues items randomly) and a subset of the Chan functions, so it still
>> doesn't prove any issue with Chan - but I am now sceptical.
>
> It's surprising how difficult it is to get these MVar-based abstractions
> right.  Some thorough testing of Chan is probably in order.

Agreed! In this project I wrote 8 different concurrency abstractions.
I had bugs in most. MVar is a great building block on which to put
higher layered abstractions, but using it correctly is tricky. I found
that I used MVar's in four ways:

1) MVar's which are always full, and are just locks around data for
consistency. Created with newMVar, used with modifyMVar.

2) MVar's which contain unit and are used for locking something other
than data (i.e. a file on disk). Created with newMVar, used with
withMVar.

3) MVar's which are used to signal computation can begin, created with
newMVarEmpty, given to someone who calls putMVar (), and waited on by
the person who created them.

4) MVar's which go in a higher-level concurrency operation - CountVars
(variables which wait until they have been signaled N times), RandChan
(Chan but with randomness), Pool (thread pool) etc.

Thanks, Neil


More information about the Glasgow-haskell-users mailing list