Friday, April 29, 2011

Empty GHC profile files and signal handling

We recently installed signal handlers in our Haskell application to clean up some stuff on program termination. Later we realised that we couldn’t do profiling anymore because the generated .prof files were empty. We were catching SIGTERM and SIGINT (using System.Posix.Signals) to run our cleanup signal handler. As signal handlers are run in their own thread, we had to use “exitImmediately” (from System.Posix.Process) instead of “exitWith” to terminate the application. Unfortunately that call really exits immediately and doesn’t give the RTS the opportunity to write the profile.

The GHC Commentay explains that the default interrupt handler calls ”interruptStgRts” to exit the program. We now import this C-function via FFI and call it in our signal handler.

Update! We lose the ability to specify an exit code when using “interruptStgRts” so we now call “shutdownHaskellAndExit” instead.

Here’s an example program that demonstrates the use of System.Posix.Process and the FFI call to “shutdownHaskellAndExit”:

{-# LANGUAGE ForeignFunctionInterface #-}
import Control.Concurrent
import Foreign.C( CInt )
import System.IO
import System.Posix.Process
import System.Exit
import System.Posix.Signals

foreign import ccall "shutdownHaskellAndExit" shutdownHaskellAndExit :: CInt -> IO ()

firstSigINT :: IO ()
firstSigINT =
    do hPutStrLn stderr "caught interrupt (shutdown takes 2s)"
       hFlush stderr
       installHandler keyboardSignal (Catch secondSigINT) (Just emptySignalSet)
       threadDelay (2*1000*1000)
       shutdownHaskellAndExit 13

secondSigINT :: IO ()
secondSigINT =
    do hPutStrLn stderr "forcing immediate exit"
       hFlush stderr
       exitImmediately (ExitFailure 13)

main =
    do installHandler keyboardSignal (Catch firstSigINT) (Just emptySignalSet)
       let busyloop i = busyloop (i+1)
       busyloop 0

Author: David Leuschner

No comments:

Post a Comment