-
Notifications
You must be signed in to change notification settings - Fork 71
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dynamic event switching results in "*** Exception: thread blocked indefinitely in an MVar operation" deadlock #216
Comments
I decided to take a look at the source code of reactive-banana and saw this: Reactive.Banana.Internal.Combinators.compile compile :: Moment () -> IO EventNetwork
compile setup = do
actuated <- newIORef False -- flag to set running status
s <- newEmptyMVar -- setup callback machinery
let
whenFlag flag action = readIORef flag >>= \b -> when b action
runStep f = whenFlag actuated $ do
s1 <- takeMVar s -- read and take lock
-- pollValues <- sequence polls -- poll mutable data
(output, s2) <- f s1 -- calculate new state
putMVar s s2 -- write state
output -- run IO actions afterwards
eventNetwork = EventNetwork
{ runStep = runStep
, actuate = writeIORef actuated True
, pause = writeIORef actuated False
}
(output, s0) <- -- compile initial graph
Prim.compile (runReaderT setup eventNetwork) Prim.emptyNetwork
putMVar s s0 -- set initial state
return $ eventNetwork Could it be that the value of |
I managed to get the code to work by creating the event after it was first converted to a behavior: {-# LANGUAGE RecursiveDo #-}
module Main2 where
import Control.Monad (when)
import qualified Reactive.Banana as B
import qualified Reactive.Banana.Frameworks as BF
data Vars = Vars { var :: Int }
data EventType = Increase | Decrease | Jump
instance Semigroup EventType where a <> _ = a
main :: IO ()
main = do
(addHandler, fire) <- BF.newAddHandler
network <- B.compile $ eventNetworkDescription addHandler
BF.actuate network
loop fire
where
loop fire = do
s <- getLine
case s of
"i" -> fire Increase
"d" -> fire Decrease
_ -> pure ()
when (s /= "x") $ loop fire
eventNetworkDescription :: BF.AddHandler EventType -> BF.MomentIO ()
eventNetworkDescription addHandler = mdo
events <- BF.fromAddHandler addHandler
let vars = Vars 1
stateE <- B.accumE vars $ doSomethingWithState <$> (events <> feedbackEvents)
stateB <- B.stepper vars stateE
futureStateE <- BF.changes stateB
feedbackEvents <- getFeedbackEvents stateB -- <- ❗ feedbackEvents is now created here ❗
BF.reactimate' $ fmap printState <$> futureStateE
doSomethingWithState :: EventType -> (Vars -> Vars)
doSomethingWithState Increase (Vars n) = Vars (n + 1)
doSomethingWithState Decrease (Vars n) = Vars (n - 1)
doSomethingWithState Jump _ = Vars 1000
getFeedbackEvents :: B.Behavior Vars -> BF.MomentIO (B.Event EventType)
getFeedbackEvents b = do
(e, fire) <- BF.newEvent
eb <- BF.changes b
BF.reactimate' $ fmap (fire . varToEvent) <$> eb
pure $ B.filterJust e
where
varToEvent :: Vars -> Maybe EventType
varToEvent (Vars 5) = Just Jump
varToEvent _ = Nothing
printState :: Vars -> IO ()
printState (Vars n) = print n But I still feel like it should work the original way I had it too instead of with this work-around... :/ |
There's definitely something up here, because I'm also getting this in my app. I'm pretty sure the bug happens if you try and fire events in your imageChanged <- switchE =<< execute do
imagePathChanges <&> \newPath -> do
(imageLoaded, onImageLoad) <- newEvent
liftIO do
onImageLoad =<< imdecode ImreadColor <$> BS.readFile newPath
return imageLoaded But if I comment out that middle I note that in your example, |
That might be the issue yes, but still strange that it happens. |
I think this is a duplicate of #190 |
Hello! Yes, this is a duplicate of #190 . Sorry about that — it's a feature, not a bug! Creating a new event handler will reorganize the |
If it is working as intended, is the way I "solved" it the way to go? |
@PiJoKra Uh, could you be more specific about what you want to do? I don't quite understand how It seems that you want some sort of recursion? You do have to be very careful when |
Sorry for my late reply. Yes I am looking for recursion. An event triggering another event. Take for example a video game: an event causes your character to walk to a wall which should cause a collision-event that can be acted upon. What is the best way to handle such a situation? I feel like I am missing something. Edit: I was wondering why I did it the way I did by translating the
Since the answer there already mentions ...
... I am wondering if your stance has changed from "This is a decision that Conal Elliott made in his original FRP semantics and I've decided to stick to it." |
The collision-event will be fine as long as it's not recursive — if you try to make the event that walks the character into the wall depend on the collision, then you may end up with conflicting semantics where the collision only happens if the character walks into a wall, but once a collision happens, the character will not walk into a wall — but this implies that no collision happens. Disallowing recursion of Events forces you to make up your mind on the semantics of this situation. |
(As this discussion does not qualify as an "issue" anymore, i.e. a defect or enhancement, I'm moving it to the Discussion forum.) |
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
Hello,
While working on an application I noticed that the application hang any moment I created a new event from an event callback.
I decided to create a little application to test if it was my code, my misunderstanding of the framework or a bug.
I think I already ruled out the first option, as I get the exception "*** Exception: thread blocked indefinitely in an MVar operation" when I run the code below in GHCi.
You can enter "i" and "d" to increase or decrease the value in the state, and if the state gets to 5 it jumps to 1000. It is that jump that is causing the problems.
Do you know if I am doing something wrong or if this is a bug? Thanks in advance!
The text was updated successfully, but these errors were encountered: