2

I'm creating a Happstack server application, but I don't know how to end the application .

If I have:

main = do
  printf "begin server"
  simpleHTTP nullConf myHomepage
  printf "end server"

I can run it ok, and I can kill the application (linux) with CTRL+C, but the last print is never executed. How can I exit gracefully from Happstack? It bothers me because I notice that eventlog is not generated if I don't exit correctly from the application.

UPDATE:

The application is using Dyre at the top main.

Zhen
  • 4,171
  • 5
  • 38
  • 57

2 Answers2

3

I generally use forkIO to spawn simpleHTTP in a separate thread. And then waitForTermination to wait for ^C.

module Main where

import Control.Concurrent (killThread, forkIO)
import Happstack.Server (nullConf, simpleHTTP, ok, toResponse)
import Happstack.State (waitForTermination)

main :: IO ()
main =
    do putStrLn "begin server"
       httpThreadId <- forkIO $ simpleHTTP nullConf (ok $ toResponse "This site rules!")
       waitForTermination
       killThread httpThreadId
       putStrLn "end server"

waitForTermination comes from the happstack-state package. It really needs to be moved somewhere else for multiple reasons. If you don't want to install happstack-state you can copy and paste a local copy into your app:

-- | Wait for a signal.
--   On unix, a signal is sigINT or sigTERM. 
waitForTermination :: IO ()
waitForTermination
    = do istty <- queryTerminal stdInput
         mv <- newEmptyMVar
         installHandler softwareTermination (CatchOnce (putMVar mv ())) Nothing
         case istty of
           True  -> do installHandler keyboardSignal (CatchOnce (putMVar mv ())) Nothing
                       return ()
           False -> return ()
         takeMVar mv
stepcut
  • 1,502
  • 8
  • 10
0

Run the simpleHTTP (which is a IO action) on a seperate thread using forkIO, then on main method you can exit any time you want.

Try something like:

main = do
    printf "begin server"
    threadID <- forkIO $ simpleHTTP nullConf myHomepage
    c <- getChar
    printf "Quiting"
Ankur
  • 33,367
  • 2
  • 46
  • 72
  • It's a solution that should work, I found more information on http://stackoverflow.com/questions/5589799/control-thread-to-exit-haskell-application – Zhen Sep 05 '11 at 10:06
  • The forkIO doesn't work at all. I try to put th fork both in simpleHTTP and in waitForQ function. Maybe the problem it's related to Dyre? – Zhen Sep 05 '11 at 10:59
  • Updated my answer, pls try that – Ankur Sep 05 '11 at 11:03
  • The updated version also don't work (it's simplier that the one a try before, that calls hSetBuffering stdin NoBuffering) – Zhen Sep 05 '11 at 11:37
  • By it doesn't work you mean it exit quickly or the HTTP server doesn't run ? – Ankur Sep 05 '11 at 11:41
  • I mean, the program only exit when I press CTRL-C. It never print "Quiting" String, And it does not get the char (I press "Q" and [return] and nothing occurs) – Zhen Sep 05 '11 at 11:46
  • It works for me (prints `Quiting`) when I press [return]. (Though, I need to to add `\n` to the strings so that they printed at the right time). CTRL-C still kills the app prematurely since nothing is done to trap the signal. – stepcut Sep 06 '11 at 00:17