summaryrefslogtreecommitdiff
path: root/src/GF/System/Signal.hs
diff options
context:
space:
mode:
authorbringert <unknown>2005-11-07 19:15:05 +0000
committerbringert <unknown>2005-11-07 19:15:05 +0000
commitabf9823601eac8beb9281ef5cd48e088793442b2 (patch)
tree62bcccf68390de7b50947725208d97cfa320cd07 /src/GF/System/Signal.hs
parentc113c20862508c8150b5373a2aafc27fafc79e93 (diff)
Allow interrupting commands with Ctrl-C. Catch exceptions throw by commands.
Diffstat (limited to 'src/GF/System/Signal.hs')
-rw-r--r--src/GF/System/Signal.hs47
1 files changed, 47 insertions, 0 deletions
diff --git a/src/GF/System/Signal.hs b/src/GF/System/Signal.hs
new file mode 100644
index 000000000..7c39a53ca
--- /dev/null
+++ b/src/GF/System/Signal.hs
@@ -0,0 +1,47 @@
+----------------------------------------------------------------------
+-- |
+-- Module : GF.System.Signal
+-- Maintainer : Bjorn Bringert
+-- Stability : (stability)
+-- Portability : (portability)
+--
+-- > CVS $Date: 2005/11/07 20:15:05 $
+-- > CVS $Author: bringert $
+-- > CVS $Revision: 1.1 $
+--
+-- Allows SIGINT (Ctrl-C) to interrupt computations.
+-----------------------------------------------------------------------------
+
+module GF.System.Signal where
+
+import Control.Concurrent (myThreadId, killThread)
+import Control.Exception (Exception,catch)
+import Prelude hiding (catch)
+import System.IO
+import System.Posix.Signals
+
+-- | Run an IO action, and allow it to be interrupted
+-- by a SIGINT to the current process. Returns
+-- an exception if the process did not complete
+-- normally.
+-- NOTES:
+-- * This will replace any existing SIGINT
+-- handlers, and after the computation has completed
+-- the default handler will be installed for SIGINT.
+-- * If the IO action is lazy (e.g. using readFile,
+-- unsafeInterleaveIO etc.) the lazy computation will
+-- not be interruptible, as it will be performed
+-- after the signal handler has been removed.
+runInterruptibly :: IO a -> IO (Either Exception a)
+runInterruptibly a = do t <- myThreadId
+ installHandler sigINT (Catch (killThread t)) Nothing
+ x <- p `catch` h
+ installHandler sigINT Default Nothing
+ return x
+ where p = a >>= \x -> return $! Right $! x
+ h e = return $ Left e
+
+-- | Like 'runInterruptibly', but always returns (), whether
+-- the computation fails or not.
+runInterruptibly_ :: IO () -> IO ()
+runInterruptibly_ = fmap (either (const ()) id) . runInterruptibly