5

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?

dfeuer
  • 48,079
  • 5
  • 63
  • 167
smilingbuddha
  • 14,334
  • 33
  • 112
  • 189
  • 1
    Possibly unrelated, but I have some dependency issues which cause `play` to produce what appears to be an exception (`tmp: user error (unknown GLUT entry glutInit)`), so perhaps closing the window also causes an unhandled exception? – chepner Sep 21 '16 at 02:27
  • Looks like a buffering problem. Try to flush stout before exiting `hFlush stdout` – mb14 Sep 21 '16 at 09:58
  • @mb14 I still get the same problem :-( – smilingbuddha Sep 21 '16 at 13:03
  • Tested in Windows 10 : on closing, ghci tells `freeglut (): fghInitialize: CreateDC failed, Screen size info may be incorrect This is quite likely caused by a bad '-display' parameter` and then crashes, even with an exception handler around `play`. – V. Semeria Sep 21 '16 at 14:03

1 Answers1

2

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.

user2407038
  • 14,400
  • 3
  • 29
  • 42