{-# LANGUAGE DoAndIfThenElse #-} module Spy.Run ( runIndefinitely ) where import Control.Concurrent import qualified Control.Exception as E import System.Exit import System.IO (isEOF) import System.Posix.Signals -- | 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