[Haskell-cafe] STM and unsafePerformIO/bracket

Rob Leslie rob at mars.org
Mon Feb 3 10:50:39 UTC 2014


I’ve run into a difficulty I’d appreciate some advice to solve.

I am trying to make a call to C (through the FFI) within an STM transaction to compute what is effectively a pure result. By itself this doesn’t seem to be a problem, except that the C function depends on some global state in a way that compromises thread safety, and so I would like to serialize the process of setting up that state and calling the FFI.

I have tried wrapping my call up with:

>  unsafePerformIO $ bracket (takeMVar lock) (putMVar lock) $ \_ -> do
>    setupFFIGlobalState
>    callFFI

This seems to work as intended, with one significant exception. If the surrounding STM transaction is aborted (i.e. because of a TVar conflict detected by another thread) while inside the bracket, then apparently the second argument to ‘bracket’ may never be evaluated, leaving my ‘lock’ mutex forever empty, and eventually causing deadlock.

Here is a working example of the problem:

  http://lpaste.net/99399

When I run that, I get:

  taking lock...
  lock acquired
  taking lock...
  stm-test: thread blocked indefinitely in an MVar operation

Is this expected behavior? I realize performing any IO within an STM transaction is inherently unsafe, but I am a little surprised that ‘bracket’ fails here.

Is there a better way to do what I’m trying to accomplish? How can I provide a pure interface to my foreign function that will work within an STM transaction?

Thanks,

-- 
Rob Leslie
rob at mars.org




More information about the Haskell-Cafe mailing list