packages feed

spy-0.10: src/Spy/Run.hs

{-# LANGUAGE DoAndIfThenElse #-}

module Spy.Run (
    runIndefinitely
) where


import           System.IO          (isEOF)
import           System.Exit
import           System.Posix.Signals
import           Control.Concurrent
import qualified Control.Exception as E

-- | Run indefinitely until the users aborts (via CTRL-D, CTRL-C or by sending a TERM
-- signal)
-- The `start` funtion will be called once, the cleanup once when the user
-- aborts with the result of the start function as the argument.
runIndefinitely :: IO b -> (b -> IO a) -> IO ()
runIndefinitely start cleanup = do
    tid <- myThreadId
    res <- start
    let handler = CatchOnce . terminate res tid
    installHandler sigINT (handler 130) Nothing -- CTRL-C
    installHandler sigTERM (handler 143) Nothing
    loop res
    where loop res = do
            finished <- isEOF
            if finished then do
                cleanup res
                return ()
            else do
                _ <- getLine
                loop res
          terminate res tid exit = do
            cleanup res
            E.throwTo tid $ ExitFailure exit