[Git][ghc/ghc][wip/romes/exceptions-propagate] Fix exception backtraces from GHCi

Rodrigo Mesquita (@alt-romes) gitlab at gitlab.haskell.org
Wed Oct 2 10:32:53 UTC 2024



Rodrigo Mesquita pushed to branch wip/romes/exceptions-propagate at Glasgow Haskell Compiler / GHC


Commits:
0ece3288 by Rodrigo Mesquita at 2024-10-02T11:32:12+01:00
Fix exception backtraces from GHCi

When running the program with `runhaskell`/`runghc` the backtrace should
match the backtrace one would get by compiling and running the program.
But currently, an exception thrown in a program interpreted with
`runhaskell` will:

    * Not include the original exception backtrace at all
    * Include the backtrace from the internal GHCi/ghc rethrowing of the
      original exception

This commit fixes this divergence by not annotating the ghc(i) backtrace
(with NoBacktrace) and making sure that the backtrace of the original
exception is serialized across the boundary and rethrown with the
appropriate context.

Fixes #25116

- - - - -


3 changed files:

- ghc/GHCi/UI/Monad.hs
- libraries/ghci/GHCi/Message.hs
- libraries/ghci/GHCi/Run.hs


Changes:

=====================================
ghc/GHCi/UI/Monad.hs
=====================================
@@ -73,6 +73,7 @@ import Control.Monad
 import Prelude hiding ((<>))
 
 import System.Console.Haskeline (CompletionFunc, InputT)
+import Control.Exception
 import Control.Monad.Catch as MC
 import Control.Monad.Trans.Class
 import Control.Monad.Trans.Reader
@@ -212,7 +213,9 @@ data CommandResult
    deriving Show
 
 cmdSuccess :: MonadThrow m => CommandResult -> m (Maybe Bool)
-cmdSuccess CommandComplete{ cmdResult = Left e } = throwM e
+cmdSuccess CommandComplete{ cmdResult = Left e } =
+  {- Don't add a backtrace from ghci/ghc to the exception from the user program! -}
+  throwM (NoBacktrace e)
 cmdSuccess CommandComplete{ cmdResult = Right r } = return r
 cmdSuccess CommandIncomplete = return $ Just True
 


=====================================
libraries/ghci/GHCi/Message.hs
=====================================
@@ -40,6 +40,9 @@ import GHC.Fingerprint
 import GHC.Conc (pseq, par)
 import Control.Concurrent
 import Control.Exception
+#if MIN_VERSION_base(4,20,0)
+import Control.Exception.Context
+#endif
 import Data.Binary
 import Data.Binary.Get
 import Data.Binary.Put
@@ -442,7 +445,15 @@ toSerializableException :: SomeException -> SerializableException
 toSerializableException ex
   | Just UserInterrupt <- fromException ex  = EUserInterrupt
   | Just (ec::ExitCode) <- fromException ex = (EExitCode ec)
-  | otherwise = EOtherException (show (ex :: SomeException))
+  | otherwise = EOtherException $
+#if MIN_VERSION_base(4,20,0)
+      -- Exception plus backtrace as seen in `displayExceptionWithInfo`
+      case displayExceptionContext (someExceptionContext ex) of
+        "" -> displayException (ex :: SomeException)
+        cx -> displayException (ex :: SomeException) ++ "\n\n" ++ cx
+#else
+      show (ex :: SomeException)
+#endif
 
 fromSerializableException :: SerializableException -> SomeException
 fromSerializableException EUserInterrupt = toException UserInterrupt


=====================================
libraries/ghci/GHCi/Run.hs
=====================================
@@ -252,7 +252,7 @@ sandboxIO opts io = do
 --
 rethrow :: EvalOpts -> IO a -> IO a
 rethrow EvalOpts{..} io =
-  catch io $ \se -> do
+  catchNoPropagate io $ \(ExceptionWithContext cx se) -> do
     -- If -fbreak-on-error, we break unconditionally,
     --  but with care of not breaking twice
     if breakOnError && not breakOnException
@@ -263,7 +263,7 @@ rethrow EvalOpts{..} io =
                Just UserInterrupt -> return ()
                -- In any other case, we don't want to break
                _ -> poke exceptionFlag 0
-    throwIO se
+    rethrowIO (ExceptionWithContext cx se)
 
 --
 -- While we're waiting for the sandbox thread to return a result, if



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/0ece32881a3dd78d364d6c2ae325388a2c44152f

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/0ece32881a3dd78d364d6c2ae325388a2c44152f
You're receiving this email because of your account on gitlab.haskell.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20241002/ea8ae07a/attachment-0001.html>


More information about the ghc-commits mailing list