writeChan not properly protecting again async exceptions
|Reported by:||klao||Owned by:|
|Type of failure:||None/Unknown||Difficulty:||Unknown|
|Test Case:||Blocked By:|
In the current code of writeChan from Control.Concurrent.Chan:
writeChan (Chan _ writeVar) val = do new_hole <- newEmptyMVar modifyMVar_ writeVar $ \old_hole -> do putMVar old_hole (ChItem val new_hole) return new_hole
if an async exception arrives "between" putMVar old_hole and return, the channel will be left in inconsistent state: the writeVar will be reverted to its original value, but old_hole would remain filled in. Thus all subsequent writers will block on this Chan indefinitely.
The proper solution is to just mask the whole operation. And it's OK, as 'putMVar old_hole' cannot ever block. I attach a patch for this.