on master help sign in
don't launch if server fails; kill server on exit #537

Make the server thread and launch/monitor thread more aware of each other, using async. Now, we won't launch a browser until the server is ready to serve pages, and we won't launch it at all if the server fails to start. Also we make sure to terminate the server thread whenever the main thread terminates, eg from ctrl-c in GHCI.

commit6f7f5b67fbd244a35d514abf3d7cd9a805a18479 authorSimon Michael <simon@joyful.com> dateFri 22 Apr 2016, 10:02 (10 years ago) parentea02528
2 files changed+18−9
wai-handler-launch/Network/Wai/Handler/Launch.hs+17−9 wai-handler-launch/wai-handler-launch.cabal+1
wai-handler-launch/Network/Wai/Handler/Launch.hs+17−9
@@ -15,7 +15,8 @@ import qualified Network.Wai.Handler.Warp as Warp
1515import Data.IORef
1616import Data.Monoid (mappend)
1717import Data.String (fromString)
18−import Control.Concurrent (forkIO, threadDelay)
18+import Control.Concurrent (forkIO, threadDelay, newEmptyMVar, putMVar, takeMVar)
19+import Control.Concurrent.Async (race)
1920import Control.Monad.IO.Class (liftIO)
2021import Control.Monad (unless)
2122import Control.Exception (throwIO)
@@ -192,14 +193,21 @@ runUrlPort = runHostPortUrl "*4"
192193
193194runHostPortUrl :: String -> Int -> String -> Application -> IO ()
194195runHostPortUrl host port url app = do
195− x <- newIORef True
196− _ <- forkIO $ Warp.runSettings
197− ( Warp.setPort port
198− $ Warp.setOnException (\_ _ -> return ())
199− $ Warp.setHost (fromString host) Warp.defaultSettings)
200− $ ping x app
201− launch port url
202− loop x
196+ ready <- newEmptyMVar
197+ active <- newIORef True
198+ let settings =
199+ Warp.setPort port $
200+ Warp.setOnException (\_ _ -> return ()) $
201+ Warp.setHost (fromString host) $
202+ Warp.setBeforeMainLoop (putMVar ready ()) $
203+ Warp.defaultSettings
204+ -- Run these threads concurrently; when either one terminates or
205+ -- raises an exception, the same happens to the other.
206+ fmap (either id id) $ race
207+ -- serve app, keep updating the activity flag
208+ (Warp.runSettings settings (ping active app))
209+ -- wait for server startup, launch browser, poll until server idle
210+ (takeMVar ready >> launch port url >> loop active)
203211
204212loop :: IORef Bool -> IO ()
205213loop x = do
wai-handler-launch/wai-handler-launch.cabal+1
@@ -21,6 +21,7 @@ Library
2121 , bytestring >= 0.9.1.4
2222 , blaze-builder >= 0.2.1.4 && < 0.5
2323 , streaming-commons
24+ , async
2425
2526 if os(windows)
2627 c-sources: windows.c