[project @ 2001-11-07 18:18:51 by sof]
[ghc-hetmet.git] / ghc / lib / std / PrelTopHandler.hs
1 {-# OPTIONS -#include "PrelIOUtils.h" #-}
2 -- -----------------------------------------------------------------------------
3 --
4 -- (c) The University of Glasgow, 1994-
5 --
6 -- PrelTopHandler
7 --
8 -- 'Top-level' IO actions want to catch exceptions (e.g., forkIO and 
9 -- PrelMain.mainIO) and report them - topHandler is the exception
10 -- handler they should use for this:
11
12 -- make sure we handle errors while reporting the error!
13 -- (e.g. evaluating the string passed to 'error' might generate
14 --  another error, etc.)
15
16 -- These functions can't go in PrelMain, because PrelMain isn't
17 -- included in HSstd.o (because PrelMain depends on Main, which
18 -- doesn't exist yet...).
19 --
20 -- Note: used to be called PrelTopHandler.lhs, so if you're looking
21 --       for CVS info, try 'cvs log'ging it too.
22 module PrelTopHandler (
23    topHandler, reportStackOverflow, reportError 
24   ) where
25
26 import IO
27
28 import PrelCString
29 import PrelPtr
30 import PrelIOBase
31 import PrelException
32
33 topHandler :: Exception -> IO ()
34 topHandler err = catchException (real_handler err) topHandler
35
36 real_handler :: Exception -> IO ()
37 real_handler ex =
38   case ex of
39         AsyncException StackOverflow -> reportStackOverflow True
40
41         -- only the main thread gets ExitException exceptions
42         ExitException ExitSuccess     -> shutdownHaskellAndExit 0
43         ExitException (ExitFailure n) -> shutdownHaskellAndExit n
44
45         ErrorCall s -> reportError True s
46         other       -> reportError True (showsPrec 0 other "\n")
47
48 -- NOTE: shutdownHaskellAndExit must be called "safe", because it *can*
49 -- re-enter Haskell land through finalizers.
50 foreign import ccall "shutdownHaskellAndExit" 
51   shutdownHaskellAndExit :: Int -> IO ()
52
53 reportStackOverflow :: Bool -> IO ()
54 reportStackOverflow bombOut = do
55    (hFlush stdout) `catchException` (\ _ -> return ())
56    callStackOverflowHook
57    if bombOut then
58      stg_exit 2
59     else
60      return ()
61
62 reportError :: Bool -> String -> IO ()
63 reportError bombOut str = do
64    (hFlush stdout) `catchException` (\ _ -> return ())
65    withCStringLen str $ \(cstr,len) -> do
66      writeErrString errorHdrHook cstr len
67      if bombOut 
68         then stg_exit 1
69         else return ()
70
71 #ifndef ILX
72 foreign label "ErrorHdrHook" errorHdrHook :: Ptr ()
73 #else
74 foreign import "_ErrorHdrHook" errorHdrHook :: Ptr ()
75 #endif
76
77 foreign import ccall "writeErrString__" unsafe
78         writeErrString :: Ptr () -> CString -> Int -> IO ()
79
80 -- SUP: Are the hooks allowed to re-enter Haskell land?  If so, remove
81 -- the unsafe below.
82 foreign import ccall "stackOverflow" unsafe
83         callStackOverflowHook :: IO ()
84
85 foreign import ccall "stg_exit" unsafe
86         stg_exit :: Int -> IO ()
87