Skip to content

Modify displayed exception type #261

Closed
@tbidne

Description

@tbidne

Intro

Hello, this is a follow-up to the accepted (unmerged gitlab MR) proposal: #231.

If you will recall, that issue adds the following exception metadata to the default handler:

Main: thread blocked indefinitely in an MVar operation
HasCallStack backtrace:
CallStack (from HasCallStack):
  collectBacktraces, called at libraries/base/GHC/Exception.hs:67:13 in base:GHC.Exception
  toExceptionWithBacktrace, called at libraries/base/GHC/IO.hs:278:11 in base:GHC.IO
  throwIO, called at Main.hs:15:16 in main:Main
  
-- the below is new

Package: base
Module: GHC.IO.Exception
Name: BlockedIndefinitelyOnMVar

On the issue tracker, @michaelpj observes that the message could be clearer still, with references to other programming languages. At the time I thought this was a good suggestion but didn't think it important enough to warrant the churn of another CLC-proposal and possible interference with the rest of the exceptions work. Now that the "callstacks are part of displayException" work has been merged, however, I think that has changed. In particular, the output with multiple stacktraces / #231 is complicated enough that I think getting other opinions would be wise.

Status quo

As of now, here is what the exception output currently looks like:

Expand example
  1. Default (HasCallStack only)
λ. ./Main
Main: thread blocked indefinitely in an MVar operation
HasCallStack backtrace:
  collectBacktraces, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:92:13 in ghc-internal:GHC.Internal.Exception
  toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/IO.hs:260:11 in ghc-internal:GHC.Internal.IO
  throwIO, called at Main.hs:33:16 in main:Main



  1. All backtraces off
λ. ./Main
Main: thread blocked indefinitely in an MVar operation



  1. All backtraces on (except DWARF, since that adds an error message w/o other changes)
λ. ./Main
Main: thread blocked indefinitely in an MVar operation
Cost-centre stack backtrace:
IPE backtrace:
HasCallStack backtrace:
  collectBacktraces, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:92:13 in ghc-internal:GHC.Internal.Exception
  toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/IO.hs:260:11 in ghc-internal:GHC.Internal.IO
  throwIO, called at Main.hs:33:16 in main:Main



(the trailing newlines are due to there being a "blank" annotation that nonetheless is rendered with separating newlines.)

Current proposal

With the accepted proposal, this looks like:

Expand example
  1. Default (HasCallStack only)
λ. ./Main
Main: thread blocked indefinitely in an MVar operation
HasCallStack backtrace:
  collectBacktraces, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:92:13 in ghc-internal:GHC.Internal.Exception
  toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/IO.hs:260:11 in ghc-internal:GHC.Internal.IO
  throwIO, called at Main.hs:40:16 in main:Main

Package: ghc-internal
Module: GHC.Internal.IO.Exception
Name: BlockedIndefinitelyOnMVar

  1. All backtraces off
λ. ./Main
Main: thread blocked indefinitely in an MVar operation

Package: ghc-internal
Module: GHC.Internal.IO.Exception
Name: BlockedIndefinitelyOnMVar

  1. All backtraces on
λ. ./Main
Main: thread blocked indefinitely in an MVar operation
Cost-centre stack backtrace:
IPE backtrace:
HasCallStack backtrace:
  collectBacktraces, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:92:13 in ghc-internal:GHC.Internal.Exception
  toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/IO.hs:260:11 in ghc-internal:GHC.Internal.IO
  throwIO, called at Main.hs:40:16 in main:Main

Package: ghc-internal
Module: GHC.Internal.IO.Exception
Name: BlockedIndefinitelyOnMVar

Proposed change

Taking inspiration from @michaelpj's suggestion, this could instead look like:

Expand example
  1. Default (HasCallStack only)
λ. ./Main
Main: Exception:

thread blocked indefinitely in an MVar operation

Package: ghc-internal
Module: GHC.Internal.IO.Exception
Type: BlockedIndefinitelyOnMVar

HasCallStack backtrace:
  collectBacktraces, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:92:13 in ghc-internal:GHC.Internal.Exception
  toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/IO.hs:260:11 in ghc-internal:GHC.Internal.IO
  throwIO, called at Main.hs:33:16 in main:Main



  1. All backtraces off
λ. ./Main
Main: Exception:

thread blocked indefinitely in an MVar operation

Package: ghc-internal
Module: GHC.Internal.IO.Exception
Type: BlockedIndefinitelyOnMVar




  1. All backtraces on (except DWARF)
λ. ./Main
Main: Exception:

thread blocked indefinitely in an MVar operation

Package: ghc-internal
Module: GHC.Internal.IO.Exception
Type: BlockedIndefinitelyOnMVar

Cost-centre stack backtrace:
IPE backtrace:
HasCallStack backtrace:
  collectBacktraces, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:92:13 in ghc-internal:GHC.Internal.Exception
  toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/IO.hs:260:11 in ghc-internal:GHC.Internal.IO
  throwIO, called at Main.hs:33:16 in main:Main



Notice that there is a new line Exception: and the exception type info precedes the possibly backtrace info.

The type info could also be more compact e.g. ghc-internal:GHC.Internal.IO.Exception:BlockedIndefinitelyOnMVar.

Implementation

Moving the exception type info before the backtrace info requires implementing the former in SomeException's displayException, not the default handler, in contrast to the accepted proposal. This seems plausible to me, as I could imagine a user wanting to override the handler (e.g. to log exceptions to a file) without losing the displayed type info.

Draft MR

Thanks!

CC @tomjaguarpaw @bgamari

Metadata

Metadata

Assignees

No one assigned

    Labels

    approvedApproved by CLC votebase-4.21Implemented in base-4.21 (GHC 9.12)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions