Re: Decorating exceptions with backtrace information

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Re: Decorating exceptions with backtrace information

Michael Sloan
Thanks so much for making a proposal for this, Ben!!  It's great to see progress here.

I'm also glad that there is now a proposal process.  I made a fairly similar proposal almost exactly 5 years ago to the libraries list - https://mail.haskell.org/pipermail/libraries/2015-April/025471.html - but without the subtlety of particular backtrace representations.  Skimming the ensuing thread may still be informative.

In particular, there is one thing I would like to highlight from that old proposal.  I think it'd be good to have a standard way to represent a chain of exceptions, and build this into `catch` and `finally`.  Python and Java both have a mechanism for this, and both refer to it as a "cause" exception.  When an exception is thrown during exception handling, the exception being handled is preserved as its "cause".  I find this mechanism to be incredibly useful in Java, it has made the underlying issue much clearer in many cases, and in other cases at least provides helpful context.  I have no doubt such a mechanism would have saved me many hours of debugging exceptions in Haskell systems I've worked on in the past.

I considered commenting about that directly on the proposal, but I figure this is a better place to suggest expanding the scope of the change :) .  Totally understandable if you want to keep this proposal focused on stacktraces, but I think it'd be good to consider this as a potential future improvement.

-Michael

On Thu, May 7, 2020 at 3:55 PM Ben Gamari <[hidden email]> wrote:

Hi everyone,

After a nice discussion on IRC about the unfortunate state of error
reporting in Haskell, I felt compelled to write down some long-lingering
thoughts regarding backtraces on exceptions. The result is GHC proposal
#330 [1]. I think the approach is viable and perhaps even
straightforward. I have the sketch of an implementation here [2].

Please have a look at the proposal and leave your comments. If there is
consensus it is possible that we could have this done for 8.12.

Cheers,

- Ben


[1] https://github.com/ghc-proposals/ghc-proposals/pull/330
[2] https://gitlab.haskell.org/ghc/ghc/-/merge_requests/3236
_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Reply | Threaded
Open this post in threaded view
|

Re: Decorating exceptions with backtrace information

Carter Schonwald
ben, could you please email the libraries list with this too? This seems like a core libraries / base change rather than a ghc-the-compiler change 

On Thu, May 7, 2020 at 6:57 PM Michael Sloan <[hidden email]> wrote:
Thanks so much for making a proposal for this, Ben!!  It's great to see progress here.

I'm also glad that there is now a proposal process.  I made a fairly similar proposal almost exactly 5 years ago to the libraries list - https://mail.haskell.org/pipermail/libraries/2015-April/025471.html - but without the subtlety of particular backtrace representations.  Skimming the ensuing thread may still be informative.

In particular, there is one thing I would like to highlight from that old proposal.  I think it'd be good to have a standard way to represent a chain of exceptions, and build this into `catch` and `finally`.  Python and Java both have a mechanism for this, and both refer to it as a "cause" exception.  When an exception is thrown during exception handling, the exception being handled is preserved as its "cause".  I find this mechanism to be incredibly useful in Java, it has made the underlying issue much clearer in many cases, and in other cases at least provides helpful context.  I have no doubt such a mechanism would have saved me many hours of debugging exceptions in Haskell systems I've worked on in the past.

I considered commenting about that directly on the proposal, but I figure this is a better place to suggest expanding the scope of the change :) .  Totally understandable if you want to keep this proposal focused on stacktraces, but I think it'd be good to consider this as a potential future improvement.

-Michael

On Thu, May 7, 2020 at 3:55 PM Ben Gamari <[hidden email]> wrote:

Hi everyone,

After a nice discussion on IRC about the unfortunate state of error
reporting in Haskell, I felt compelled to write down some long-lingering
thoughts regarding backtraces on exceptions. The result is GHC proposal
#330 [1]. I think the approach is viable and perhaps even
straightforward. I have the sketch of an implementation here [2].

Please have a look at the proposal and leave your comments. If there is
consensus it is possible that we could have this done for 8.12.

Cheers,

- Ben


[1] https://github.com/ghc-proposals/ghc-proposals/pull/330
[2] https://gitlab.haskell.org/ghc/ghc/-/merge_requests/3236
_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Reply | Threaded
Open this post in threaded view
|

Re: Decorating exceptions with backtrace information

Carter Schonwald


On Fri, May 8, 2020 at 9:32 AM Carter Schonwald <[hidden email]> wrote:
ben, could you please email the libraries list with this too? This seems like a core libraries / base change rather than a ghc-the-compiler change 

On Thu, May 7, 2020 at 6:57 PM Michael Sloan <[hidden email]> wrote:
Thanks so much for making a proposal for this, Ben!!  It's great to see progress here.

I'm also glad that there is now a proposal process.  I made a fairly similar proposal almost exactly 5 years ago to the libraries list - https://mail.haskell.org/pipermail/libraries/2015-April/025471.html - but without the subtlety of particular backtrace representations.  Skimming the ensuing thread may still be informative.

In particular, there is one thing I would like to highlight from that old proposal.  I think it'd be good to have a standard way to represent a chain of exceptions, and build this into `catch` and `finally`.  Python and Java both have a mechanism for this, and both refer to it as a "cause" exception.  When an exception is thrown during exception handling, the exception being handled is preserved as its "cause".  I find this mechanism to be incredibly useful in Java, it has made the underlying issue much clearer in many cases, and in other cases at least provides helpful context.  I have no doubt such a mechanism would have saved me many hours of debugging exceptions in Haskell systems I've worked on in the past.

I considered commenting about that directly on the proposal, but I figure this is a better place to suggest expanding the scope of the change :) .  Totally understandable if you want to keep this proposal focused on stacktraces, but I think it'd be good to consider this as a potential future improvement.

-Michael

On Thu, May 7, 2020 at 3:55 PM Ben Gamari <[hidden email]> wrote:

Hi everyone,

After a nice discussion on IRC about the unfortunate state of error
reporting in Haskell, I felt compelled to write down some long-lingering
thoughts regarding backtraces on exceptions. The result is GHC proposal
#330 [1]. I think the approach is viable and perhaps even
straightforward. I have the sketch of an implementation here [2].

Please have a look at the proposal and leave your comments. If there is
consensus it is possible that we could have this done for 8.12.

Cheers,

- Ben


[1] https://github.com/ghc-proposals/ghc-proposals/pull/330
[2] https://gitlab.haskell.org/ghc/ghc/-/merge_requests/3236
_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Reply | Threaded
Open this post in threaded view
|

Re: [Haskell-cafe] Decorating exceptions with backtrace information

Niklas Hambüchen
On 5/8/20 5:37 PM, Henning Thielemann wrote:
> I can imagine that it would be helpful for the user to get a stacked exception information like:
>    Parse error on line 42, column 23
>    while reading file "foo/bar"
>    while traversing directory "blabla"

That seems to be rather specific use case.
It'd be a cool feature but I'm not aware of any programming language following that interpretation so far.

I personally would be happy to be able to get the same type of stack trace for exceptions as in other programming langues (and as the proposal suggests).

> If you must debug exceptions, then this sounds like exceptions were abused for programming errors.

I'd be pretty happy to be able to debug them better; no matter if they were "abused" for anything or not, I must still debug them in practice.

Given that they traverse program flow invisibly (e.g. not lexically, like return values) and can become visible in different places than they arose, having a call stack to debug their creation would be useful.

> a callstack is not useful for a user.

Call stacks have been very useful to me as a user of non-Haskell tools so far, because they are excellent for attaching to bug reports and usually led to developers fixing my problems faster.
_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Reply | Threaded
Open this post in threaded view
|

Re: [Haskell-cafe] Decorating exceptions with backtrace information

Niklas Hambüchen
On 5/8/20 7:32 PM, Henning Thielemann wrote:
> This confirms that they are not for you, but you only forward them to the developer.

Yes, stack traces are in general for developers.

> Can someone please give me examples where current state lacks

* Currently stack traces are not printed, so users cannot forward them to the developer, even if both the users and the developers would like that.
* Developers cannot easily produce stack traces do debug unintended exceptions.
_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Reply | Threaded
Open this post in threaded view
|

Re: [Haskell-cafe] Decorating exceptions with backtrace information

Ben Gamari-3
In reply to this post by Niklas Hambüchen
Henning Thielemann <[hidden email]> writes:

> On Fri, 8 May 2020, Niklas Hambüchen wrote:
>
>> On 5/8/20 5:37 PM, Henning Thielemann wrote:
>>
>>> a callstack is not useful for a user.
>>
>> Call stacks have been very useful to me as a user of non-Haskell tools
>> so far, because they are excellent for attaching to bug reports and
>> usually led to developers fixing my problems faster.
>
> This confirms that they are not for you, but you only forward them to the
> developer.
>
>
> Can someone please give me examples where current state lacks and how they
> are addressed by the proposal(s)?
We can debate whether partial functions like `fromJust` should exist; however,
the fact of the matter is that they do exist and they are used.
Furthermore, even `base`'s own IO library (e.g. `openFile`) uses
synchronous exceptions to report errors.

This becomes particularly painful when building large systems:
Even if I am careful to avoid such functions in my own code, as my
dependency footprint grows it becomes more likely that some transitive
dependency will expose a partial interface (perhaps even without my
knowledge). This is a problem that industrial users are all too familiar
with.

Perhaps this helps to shed some light on the motivation?

Cheers,

- Ben

_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

signature.asc (497 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [Haskell-cafe] Decorating exceptions with backtrace information

Ben Gamari-3
In reply to this post by Niklas Hambüchen
Henning Thielemann <[hidden email]> writes:

> On Fri, 8 May 2020, Niklas Hambüchen wrote:
>
>> On 5/8/20 7:32 PM, Henning Thielemann wrote:
>>
>>> Can someone please give me examples where current state lacks
>>
>> * Currently stack traces are not printed, so users cannot forward them
>> to the developer, even if both the users and the developers would like
>> that.
>
> We are talking about the HasCallStack stack traces, yes?
> How is their emission addressed by extending exceptions with stack
> traces?
HasCallStack stack traces are one type of backtrace that the proposal
supports. However, it's not the only (nor is it even the most useful
sort, in my opinion).

Other mechanisms include cost center stacks from the cost-center
profiler and native stack unwinding.

>
>> * Developers cannot easily produce stack traces do debug unintended
>> exceptions.
>
> What are "unintended exceptions"?
> What is an example of an "unintended exception"?

For instance,

 * Somewhere deep in my code a colleague used `fromJust` due to a
   miscommunicated invariant

 * Somewhere in my system a `writeFile "tmp" $ repeat 'a'` failed due to
   filling the disk

 * Somewhere in my system I have a partial pattern match in a module
   which was compiled without -Wall

 * Somewhere in my system I `div` by zero due to lack of input
   validation

 * I use a record selector on a sum.

 * A logic error results in an assertion failure deep in my program, but
   it's unclear which path my program took to arrive at the assertion

This list could go on and on...

Currently the proposal does not cover asynchronous exceptions but it
wouldn't be particularly hard to extend it in this direction. This would
allow far better reporting of heap/stack overflows and MVar deadlocks
(which are particularly hard to debug at the moment).

Cheers,

- Ben

_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

signature.asc (497 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [Haskell-cafe] Decorating exceptions with backtrace information

Michal J Gajda
In reply to this post by Michael Sloan
Ben,
I agree with you that is a great idea!

I can add a few more real world examples:
* we get exception from a foreign library that we bound,
* we get an exception from a platform (I believe Windows supports
throwing exceptions to programs),
* user presses CTRL-C and we want to know where our program hanged.
* we get infamous <<loop>>, because in theory nobody wants
non-terminating programs, but in practice everybody gets them
sometimes.

I also use `ExceptT`, `EitherT` for processing large sets of data,
because that allows me to contain the errors efficiently. However from
time to time, I get an error to blow up **and I cannot even locate
which library was guilty**. It would be nice to extract them
automatically and put them into error database before they are
prioritized.
--
  Cheers
    Michał
_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Reply | Threaded
Open this post in threaded view
|

Re: [Haskell-cafe] Decorating exceptions with backtrace information

Henning Thielemann
In reply to this post by Niklas Hambüchen

On Fri, 8 May 2020, Niklas Hambüchen wrote:

>> What are "unintended exceptions"?
>> What is an example of an "unintended exception"?
>
> A recent example from my production server:
>
>    hPutBuf: resource vanished (Broken pipe)


Ok, I lookup the Haddock comment of hPutBuf and it says:

"This operation may fail with:

* ResourceVanished if the handle is a pipe or socket, and the reading end
is closed."

That is, ResourceVanished is part of the public interface and in no way
unexpected (or what "unintended" may be). I would prefer to make this
explicit in the type of hPutBuf:

hPutBuf ::
    (ResourceVanishedException e) =>
    Handle -> Ptr a -> Int -> ExceptT e IO ()

Now, what do you intend to do with the call-stack? Isn't it something you
can attach to the e value?
_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Reply | Threaded
Open this post in threaded view
|

Re: [Haskell-cafe] Decorating exceptions with backtrace information

Henning Thielemann
In reply to this post by Ben Gamari-3

On Fri, 8 May 2020, Ben Gamari wrote:

> We can debate whether partial functions like `fromJust` should exist; however,
> the fact of the matter is that they do exist and they are used.

That's not my point. I say: fromJust on Nothing is a programming error,
ok. We must debug this. HasCallStack helps here. However, it does not have
to do with exceptions or with the proposals as I understand them.

> Furthermore, even `base`'s own IO library (e.g. `openFile`) uses
> synchronous exceptions to report errors.

Right. I say: Such exceptions are part of the public interface and should
be expressed in types. If you encounter any problems when not doing this,
I would first try to solve the problem with exceptions explicit in the
type. E.g. Haddock for openFile says:

This operation may fail with:

* isAlreadyInUseError ...
* isDoesNotExistError ...
* isPermissionError ...

Thus the type should be:

openFile ::
    (AlreadyInUseException e,
     DoesNotExistException e,
     PermissionException e) =>
    FilePath -> IOMode -> ExceptT e IO Handle


> Perhaps this helps to shed some light on the motivation?

Unfortunately no. I only see the immortal confusion about (programming)
errors vs. (IO) exceptions. And I think that part of this confusion is
that IO exceptions in 'base' are hidden in the IO type and that there are
hybrid functions like 'throw' that can be called like 'error' but they
cause IO exceptions that can be caught by 'catch'.
_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs