
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@mars.org