X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=GHC%2FConsoleHandler.hs;h=223a2bb8c5af5bd8d3130d611a2e24abce147e7b;hb=41e8fba828acbae1751628af50849f5352b27873;hp=3c3d2f4b5b3a716a4e036b9ebefef4079d54ce62;hpb=a09d886b49d91f9595ec774d6ede487045545f7c;p=ghc-base.git diff --git a/GHC/ConsoleHandler.hs b/GHC/ConsoleHandler.hs index 3c3d2f4..223a2bb 100644 --- a/GHC/ConsoleHandler.hs +++ b/GHC/ConsoleHandler.hs @@ -1,4 +1,5 @@ -{-# OPTIONS_GHC -cpp #-} +{-# LANGUAGE CPP #-} + ----------------------------------------------------------------------------- -- | -- Module : GHC.ConsoleHandler @@ -17,41 +18,38 @@ module GHC.ConsoleHandler #if !defined(mingw32_HOST_OS) && !defined(__HADDOCK__) - where -import Prelude -- necessary to get dependencies right + where #else /* whole file */ - ( Handler(..) - , installHandler - , ConsoleEvent(..) - , flushConsole - ) where + ( Handler(..) + , installHandler + , ConsoleEvent(..) + , flushConsole + ) where {- -#include "Signals.h" +#include "rts/Signals.h" -} -import Prelude -- necessary to get dependencies right - import Foreign import Foreign.C -import GHC.IOBase -import GHC.Handle +import GHC.IO.FD +import GHC.IO.Exception +import GHC.IO.Handle.Types +import GHC.IO.Handle.Internals +import GHC.Conc +import Control.Concurrent.MVar import Data.Typeable +#ifdef mingw32_HOST_OS +import Data.Maybe +import GHC.Base +#endif + data Handler = Default | Ignore | Catch (ConsoleEvent -> IO ()) -data ConsoleEvent - = ControlC - | Break - | Close - -- these are sent to Services only. - | Logoff - | Shutdown - deriving (Eq, Ord, Enum, Show, Read, Typeable) - -- | Allows Windows console events to be caught and handled. To -- handle a console event, call 'installHandler' passing the -- appropriate 'Handler' value. When the event is received, if the @@ -72,35 +70,50 @@ data ConsoleEvent -- it in one of these environments. -- installHandler :: Handler -> IO Handler -installHandler handler = +installHandler handler + | threaded = + modifyMVar win32ConsoleHandler $ \old_h -> do + (new_h,rc) <- + case handler of + Default -> do + r <- rts_installHandler STG_SIG_DFL nullPtr + return (no_handler, r) + Ignore -> do + r <- rts_installHandler STG_SIG_IGN nullPtr + return (no_handler, r) + Catch h -> do + r <- rts_installHandler STG_SIG_HAN nullPtr + return (h, r) + prev_handler <- + case rc of + STG_SIG_DFL -> return Default + STG_SIG_IGN -> return Ignore + STG_SIG_HAN -> return (Catch old_h) + _ -> error "installHandler: Bad threaded rc value" + return (new_h, prev_handler) + + | otherwise = alloca $ \ p_sp -> do - rc <- + rc <- case handler of Default -> rts_installHandler STG_SIG_DFL p_sp Ignore -> rts_installHandler STG_SIG_IGN p_sp Catch h -> do v <- newStablePtr (toHandler h) - poke p_sp v - rts_installHandler STG_SIG_HAN p_sp + poke p_sp v + rts_installHandler STG_SIG_HAN p_sp case rc of STG_SIG_DFL -> return Default STG_SIG_IGN -> return Ignore STG_SIG_HAN -> do osptr <- peek p_sp oldh <- deRefStablePtr osptr - -- stable pointer is no longer in use, free it. - freeStablePtr osptr - return (Catch (\ ev -> oldh (fromConsoleEvent ev))) + -- stable pointer is no longer in use, free it. + freeStablePtr osptr + return (Catch (\ ev -> oldh (fromConsoleEvent ev))) + _ -> error "installHandler: Bad non-threaded rc value" where - toConsoleEvent ev = - case ev of - 0 {- CTRL_C_EVENT-} -> Just ControlC - 1 {- CTRL_BREAK_EVENT-} -> Just Break - 2 {- CTRL_CLOSE_EVENT-} -> Just Close - 5 {- CTRL_LOGOFF_EVENT-} -> Just Logoff - 6 {- CTRL_SHUTDOWN_EVENT-} -> Just Shutdown - _ -> Nothing - fromConsoleEvent ev = + fromConsoleEvent ev = case ev of ControlC -> 0 {- CTRL_C_EVENT-} Break -> 1 {- CTRL_BREAK_EVENT-} @@ -109,11 +122,15 @@ installHandler handler = Shutdown -> 6 {- CTRL_SHUTDOWN_EVENT-} toHandler hdlr ev = do - case toConsoleEvent ev of - -- see rts/win32/ConsoleHandler.c for comments as to why - -- rts_ConsoleHandlerDone is called here. + case toWin32ConsoleEvent ev of + -- see rts/win32/ConsoleHandler.c for comments as to why + -- rts_ConsoleHandlerDone is called here. Just x -> hdlr x >> rts_ConsoleHandlerDone ev - Nothing -> return () -- silently ignore.. + Nothing -> return () -- silently ignore.. + + no_handler = error "win32ConsoleHandler" + +foreign import ccall "rtsSupportsBoundThreads" threaded :: Bool foreign import ccall unsafe "RtsExternal.h rts_InstallConsoleEvent" rts_installHandler :: CInt -> Ptr (StablePtr (CInt -> IO ())) -> IO CInt @@ -122,11 +139,17 @@ foreign import ccall unsafe "RtsExternal.h rts_ConsoleHandlerDone" flushConsole :: Handle -> IO () -flushConsole h = - wantReadableHandle "flushConsole" h $ \ h_ -> - throwErrnoIfMinus1Retry_ "flushConsole" - (flush_console_fd (fromIntegral (haFD h_))) +flushConsole h = + wantReadableHandle_ "flushConsole" h $ \ Handle__{haDevice=dev} -> + case cast dev of + Nothing -> ioException $ + IOError (Just h) IllegalOperation "flushConsole" + "handle is not a file descriptor" Nothing Nothing + Just fd -> do + throwErrnoIfMinus1Retry_ "flushConsole" $ + flush_console_fd (fdFD fd) foreign import ccall unsafe "consUtils.h flush_input_console__" - flush_console_fd :: CInt -> IO CInt + flush_console_fd :: CInt -> IO CInt + #endif /* mingw32_HOST_OS */