ghcError, progName,
pgmError,
- panic, panicFastInt, assertPanic, trace,
+ panic, sorry, panicFastInt, assertPanic, trace,
Exception.Exception(..), showException, try, tryMost, throwTo,
#endif
import Exception
-import Control.Concurrent ( MVar, ThreadId, withMVar, newMVar )
+import Control.Concurrent ( MVar, ThreadId, withMVar, newMVar, modifyMVar_,
+ myThreadId )
import Data.Dynamic
import Debug.Trace ( trace )
import System.IO.Unsafe ( unsafePerformIO )
-- assumed to contain a location already, so we don't print one).
data GhcException
- = PhaseFailed String -- name of phase
- ExitCode -- an external phase (eg. cpp) failed
- | Interrupted -- someone pressed ^C
- | UsageError String -- prints the short usage msg after the error
+ = PhaseFailed String -- name of phase
+ ExitCode -- an external phase (eg. cpp) failed
+ | Signal Int -- some other fatal signal (SIGHUP,SIGTERM)
+ | UsageError String -- prints the short usage msg after the error
| CmdLineError String -- cmdline prob, but doesn't print usage
- | Panic String -- the `impossible' happened
+ | Panic String -- the `impossible' happened
+ | Sorry String -- the user tickled something that's known not to work yet,
+ -- and we're not counting it as a bug.
| InstallationError String -- an installation problem
| ProgramError String -- error in the user's code, probably
deriving Eq
= showString str
showGhcException (InstallationError str)
= showString str
-showGhcException (Interrupted)
- = showString "interrupted"
+showGhcException (Signal n)
+ = showString "signal: " . shows n
showGhcException (Panic s)
= showString ("panic! (the 'impossible' happened)\n"
++ " (GHC version " ++ cProjectVersion ++ " for " ++ TargetPlatform_NAME ++ "):\n\t"
++ s ++ "\n\n"
++ "Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug\n")
+showGhcException (Sorry s)
+ = showString ("sorry! (this is work in progress)\n"
+ ++ " (GHC version " ++ cProjectVersion ++ " for " ++ TargetPlatform_NAME ++ "):\n\t"
+ ++ s ++ "\n")
+
throwGhcException :: GhcException -> a
throwGhcException = Exception.throw
Panics and asserts.
\begin{code}
-panic, pgmError :: String -> a
+panic, sorry, pgmError :: String -> a
panic x = throwGhcException (Panic x)
+sorry x = throwGhcException (Sorry x)
pgmError x = throwGhcException (ProgramError x)
-- #-versions because panic can't return an unboxed int, and that's
\end{code}
\begin{code}
--- | tryMost is like try, but passes through Interrupted and Panic
+-- | tryMost is like try, but passes through UserInterrupt and Panic
-- exceptions. Used when we want soft failures when reading interface
-- files, for example.
Left se ->
case fromException se of
-- Some GhcException's we rethrow,
- Just Interrupted -> throwIO se
+ Just (Signal _) -> throwIO se
Just (Panic _) -> throwIO se
-- others we return
Just _ -> return (Left se)
\begin{code}
installSignalHandlers :: IO ()
installSignalHandlers = do
+ main_thread <- myThreadId
+ modifyMVar_ interruptTargetThread (return . (main_thread :))
+
let
- interrupt_exn = (toException Interrupted)
+ interrupt_exn = (toException UserInterrupt)
interrupt = do
withMVar interruptTargetThread $ \targets ->
case targets of
[] -> return ()
(thread:_) -> throwTo thread interrupt_exn
+
--
#if !defined(mingw32_HOST_OS)
- _ <- installHandler sigQUIT (Catch interrupt) Nothing
- _ <- installHandler sigINT (Catch interrupt) Nothing
+ _ <- installHandler sigQUIT (Catch interrupt) Nothing
+ _ <- installHandler sigINT (Catch interrupt) Nothing
+ -- see #3656; in the future we should install these automatically for
+ -- all Haskell programs in the same way that we install a ^C handler.
+ let fatal_signal n = throwTo main_thread (Signal (fromIntegral n))
+ _ <- installHandler sigHUP (Catch (fatal_signal sigHUP)) Nothing
+ _ <- installHandler sigTERM (Catch (fatal_signal sigTERM)) Nothing
return ()
#else
-- GHC 6.3+ has support for console events on Windows
sig_handler Break = interrupt
sig_handler _ = return ()
- installHandler (Catch sig_handler)
+ _ <- installHandler (Catch sig_handler)
return ()
#endif