[project @ 2004-02-13 12:13:00 by simonmar]
[haskell-directory.git] / Control / Exception.hs
index 7d66da8..e4e037e 100644 (file)
@@ -105,20 +105,27 @@ module Control.Exception (
        bracket_,       -- :: IO a -> IO b -> IO c -> IO ()
 
        finally,        -- :: IO a -> IO b -> IO a
-
+       
+#ifdef __GLASGOW_HASKELL__
+       setUncaughtExceptionHandler,      -- :: (Exception -> IO ()) -> IO ()
+       getUncaughtExceptionHandler       -- :: IO (Exception -> IO ())
+#endif
   ) where
 
 #ifdef __GLASGOW_HASKELL__
 import GHC.Base                ( assert )
 import GHC.Exception   as ExceptionBase hiding (catch)
 import GHC.Conc                ( throwTo, ThreadId )
-import GHC.IOBase      ( IO(..) )
+import GHC.IOBase      ( IO(..), IORef(..), newIORef, readIORef, writeIORef )
+import GHC.Handle       ( stdout, hFlush )
 #endif
 
 #ifdef __HUGS__
 import Hugs.Exception  as ExceptionBase
 #endif
 
+import Foreign.C.String ( CString, withCStringLen )
+
 import Prelude                 hiding ( catch )
 import System.IO.Error hiding ( catch, try )
 import System.IO.Unsafe (unsafePerformIO)
@@ -488,7 +495,7 @@ Similar arguments apply for other interruptible operations like
 
 #ifdef __HADDOCK__
 -- | If the first argument evaluates to 'True', then the result is the
--- second argument.  Otherwise an 'Assertion' exception is raised,
+-- second argument.  Otherwise an 'AssertionFailed' exception is raised,
 -- containing a 'String' with the source file and line number of the
 -- call to assert.
 --
@@ -505,3 +512,28 @@ assert :: Bool -> a -> a
 assert True x = x
 assert False _ = throw (AssertionFailed "")
 #endif
+
+
+#ifdef __GLASGOW_HASKELL__
+{-# NOINLINE uncaughtExceptionHandler #-}
+uncaughtExceptionHandler :: IORef (Exception -> IO ())
+uncaughtExceptionHandler = unsafePerformIO (newIORef defaultHandler)
+   where
+      defaultHandler :: Exception -> IO ()
+      defaultHandler ex = do
+         (hFlush stdout) `catchException` (\ _ -> return ())
+         let msg = case ex of
+               Deadlock    -> "no threads to run:  infinite loop or deadlock?"
+               ErrorCall s -> s
+               other       -> showsPrec 0 other "\n"
+         withCStringLen ("Fail: "++msg) $ \(cstr,len) -> writeErrString cstr len
+         
+foreign import ccall unsafe "writeErrString__"
+       writeErrString :: CString -> Int -> IO ()
+
+setUncaughtExceptionHandler :: (Exception -> IO ()) -> IO ()
+setUncaughtExceptionHandler = writeIORef uncaughtExceptionHandler
+
+getUncaughtExceptionHandler :: IO (Exception -> IO ())
+getUncaughtExceptionHandler = readIORef uncaughtExceptionHandler
+#endif