diff options
author | Simon Marlow <marlowsd@gmail.com> | 2015-06-25 14:21:44 +0100 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2015-06-29 10:26:30 +0100 |
commit | bb0e462b6cff02737d67f496d8172207042c22b5 (patch) | |
tree | 43c85a31ac20781618d9e5dd531a9814be92e050 /ghc | |
parent | 302d937782ccb3068244e948d49daff3435e05c0 (diff) | |
download | haskell-bb0e462b6cff02737d67f496d8172207042c22b5.tar.gz |
Mask to avoid uncaught ^C exceptions
Summary: It was possible to kill GHCi with a carefully-timed ^C
Test Plan: The bug in #10017 exposed this
Reviewers: bgamari, austin
Reviewed By: austin
Subscribers: thomie, bgamari
Differential Revision: https://phabricator.haskell.org/D1015
GHC Trac Issues: #10017
Diffstat (limited to 'ghc')
-rw-r--r-- | ghc/InteractiveUI.hs | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/ghc/InteractiveUI.hs b/ghc/InteractiveUI.hs index a0223c184c..d392327922 100644 --- a/ghc/InteractiveUI.hs +++ b/ghc/InteractiveUI.hs @@ -553,7 +553,10 @@ runGHCi paths maybe_exprs = do -- this used to be topHandlerFastExit, see #2228 runInputTWithPrefs defaultPrefs defaultSettings $ do -- make `ghc -e` exit nonzero on invalid input, see Trac #7962 - runCommands' hdle (Just $ hdle (toException $ ExitFailure 1) >> return ()) (return Nothing) + _ <- runCommands' hdle + (Just $ hdle (toException $ ExitFailure 1) >> return ()) + (return Nothing) + return () -- and finally, exit liftIO $ when (verbosity dflags > 0) $ putStrLn "Leaving GHCi." @@ -712,12 +715,16 @@ installInteractivePrint (Just ipFun) exprmode = do -- | The main read-eval-print loop runCommands :: InputT GHCi (Maybe String) -> InputT GHCi () -runCommands = runCommands' handler Nothing +runCommands gCmd = runCommands' handler Nothing gCmd >> return () runCommands' :: (SomeException -> GHCi Bool) -- ^ Exception handler -> Maybe (GHCi ()) -- ^ Source error handler - -> InputT GHCi (Maybe String) -> InputT GHCi () -runCommands' eh sourceErrorHandler gCmd = do + -> InputT GHCi (Maybe String) + -> InputT GHCi (Maybe Bool) + -- We want to return () here, but have to return (Maybe Bool) + -- because gmask is not polymorphic enough: we want to use + -- unmask at two different types. +runCommands' eh sourceErrorHandler gCmd = gmask $ \unmask -> do b <- ghandle (\e -> case fromException e of Just UserInterrupt -> return $ Just False _ -> case fromException e of @@ -726,12 +733,12 @@ runCommands' eh sourceErrorHandler gCmd = do return Nothing _other -> liftIO (Exception.throwIO e)) - (runOneCommand eh gCmd) + (unmask $ runOneCommand eh gCmd) case b of - Nothing -> return () + Nothing -> return Nothing Just success -> do when (not success) $ maybe (return ()) lift sourceErrorHandler - runCommands' eh sourceErrorHandler gCmd + unmask $ runCommands' eh sourceErrorHandler gCmd -- | Evaluate a single line of user input (either :<command> or Haskell code). -- A result of Nothing means there was no more input to process. |