smilingbuddha
smilingbuddha

Reputation: 14660

Why does my program exit immediately after playing a gloss animation?

I am learning how to use the Gloss library to make some animations in Haskell.

Consider the code below which animates a circle that shrinks and expands its radius with time.

import Graphics.Gloss
import Graphics.Gloss.Interface.Pure.Game

type Radius = Float
type RealTime   = Float

data World = World Radius RealTime

main :: IO ()
main
 = do   let initWorld = World 100.0 0
        let windowSize = (800,800)
        let windowPosition = (200,200)
        putStrLn "Before play"
        play (InWindow "Wobbling Circle" windowSize windowPosition)
              white 40 initWorld renderWorld handleEvent stepWorld
        putStrLn "After play"

renderWorld :: World -> Picture
renderWorld (World rad rtime ) = Pictures [ Circle rad ]

handleEvent :: Event -> World -> World
handleEvent _ = id

stepWorld ::  Float -> World -> World -- wobbling circle
stepWorld  _ (World _ rtime)  = World (100 * sin rtime) (rtime+0.1) 

I compiled this code with ghc --make -O2 -threaded Main.hs on an Ubuntu 14.04 machine.

When I run the code, the "Before play" statement is printed out and then the animation starts as expected. However, when I close the animation window, the code terminates immediately without printing the "After Play" statement. Why is that?

Upvotes: 5

Views: 1044

Answers (1)

user2407038
user2407038

Reputation: 14578

Presumably you are using the GLUT backend (the default). Take a look at some of the source code for gloss (exactly as it appears with comments):

instance Backend GLUTState where
        initBackendState           = glutStateInit
        initializeBackend          = initializeGLUT

        -- non-freeglut doesn't like this: (\_ -> GLUT.leaveMainLoop)
        exitBackend                = (\_ -> System.exitWith System.ExitSuccess)

....

When it exits the main loop, gloss will call exitBackend, whatever it is. For GLUT, that simply calls System.exitWith which naturally will terminate your program. The more sensible thing to do would be to call leaveMainLoop but as the comment in the code says, implementations of glut other than freeglut don't work well with that function (why? who knows. This is what the authors of gloss claim).

Your potential solutions are to use freeglut specifically and modify the source code of gloss to change exitBackend; or use the GLFW backend, which doesn't have this problem.

Upvotes: 2

Related Questions