How to handle or throw a BlockedIndefinitelyOnSTM exception?

I spent a lot of time fixing the problem that occurred in my application that I am working on. This application is a web application displaying REST endpoints using scotty. It uses TVar to store its state, which is updated using STM a actions initiated by the interface.

Since this application is based on the principles of event search, any event created by the business layer after the completion of STM transactions is stored in EventStore (currently a simple flat file ...). Here is the relevant code snippet:

 newtype (EventStore m) => WebStateM sma = WebStateM { runWebM :: ReaderT (TVar s) ma } deriving (Functor,Applicative,Monad, MonadIO, MonadTrans, MonadReader (TVar s)) applyCommand :: (EventStore m, Serializable (Event a)) => Command a -> TVar s -> WebStateM sm (Event a) applyCommand command = \ v -> do (e, etype :: EventType s) <- liftIO $ atomically $ actAndApply v storeEvent e etype return e where actAndApply = \ v -> do s <- readTVar v let view = getView s let e = view `act` command let bv = view `apply` e modifyTVar' v (setView bv) return (e, getType view) 

This works fine until the error disappears in the storeEvent function. This function is responsible for serializing the event with the appropriate type, and I made a (gross) error in my serialization procedure for some type, which leads to an infinite loop! Then all of a sudden, my cabal test started to cabal test and fail with a timeout (I use wreq as a client library for testing REST services). It took me a couple of hours to fix the actual error on the server side: tests: thread blocked indefinitely in an STM transaction . Suspecting the serialization procedure, it took me a couple more hours to nail the culprit and fix the problem.

Although I, of course, am completely responsible for the error (I had to check my serialization procedure more carefully!), I found it quite misleading. I would like to better understand where this error came from and how to prevent it. I read Edward Young's post on this subject and this mail flow, but I must admit that the logical chain of events leading to observing this error is not entirely clear to me.

I think I understand the thread calling applyCommand that scotty throws is dying from some kind of exception (stack exhausted?) storeEvent fired while evaluating storeEvent , but I don’t understand how this relates to the transaction being garbage.

+4
source share
1 answer

The exception indicates that one thread tried to complete the transaction and clicked retry , which will restart the transaction when something changes. But what awaits change is not mentioned anywhere else, so repetition will never happen. And this is a mistake. Basically, this thread is now hanging.

I would suggest that some thread was supposed to update this TVar , but it died due to an exception, thereby discarding the last link to this TVar and causing an exception.

What I think happened. Without seeing the entire application, it’s hard to be sure.

+3
source

Source: https://habr.com/ru/post/1203412/


All Articles