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

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?
* Developers cannot easily produce stack traces do debug unintended exceptions.
What are "unintended exceptions"? What is an example of an "unintended exception"?

Henning Thielemann
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

On Fri, 8 May 2020, Ben Gamari wrote:
Henning Thielemann
writes: 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.
Interesting. That's a completely new thing.
* 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
That's a programming error.
* Somewhere in my system a `writeFile "tmp" $ repeat 'a'` failed due to filling the disk
Hm, that's also a programming error, but it ends in an IO exception. If it would not end in an IO exception (e.g. writing to /dev/null) it would go to an infinite loop. Anyway, it is a programming error. However it is an unchecked one. That is, there is no warranty that you can catch it by a debugger. So I do not think you can achieve much with callstacks here.
* Somewhere in my system I have a partial pattern match in a module which was compiled without -Wall
Programming error and btw. before thinking about a GHC extension I would enable -Wall ...
* Somewhere in my system I `div` by zero due to lack of input validation
Programming error
* I use a record selector on a sum.
Programming error
* 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
Sounds like Programming error
This list could go on and on...
From your list of examples I deduce that the proposal is about programming errors. But we have HasCallStack for that one. How does the proposal improve or alter the HasCallStack solution? And how does it relate to the IO exception system with hierarchical exceptions and SomeException and so 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).
Hm, what kind of heap or stack overflow are you thinking of? A stack overflow sounds like unlimited recursion and thus like a programming error. In contrast to that, a program must be prepared for a failure of "malloc". Memory exhaustion is an IO exception, it should be explicit in the type. Are MVar deadlocks always detected by the runtime system?

Am 12.05.20 um 23:29 schrieb Henning Thielemann:
A stack overflow sounds like unlimited recursion and thus like a programming error.
Perhaps it was just one recursion to many? Computer memory is limited. Heap overflow is also quite possible even with a program that is provably terminating. I have used 'ulimit -v' in the past to force ghc to fail rather than having to reboot my machine :-/
In contrast to that, a program must be prepared for a failure of "malloc".
I don't see any essential difference between allocation by the runtime and explicit allocation using malloc. I think this is a good thing that in Haskell you /can/ recover from such a condition.
Memory exhaustion is an IO exception, it should be explicit in the type.
Then it must be explicit in all types, since in general all computations may exhaust the available memory. And then what use would that type information have?
Are MVar deadlocks always detected by the runtime system?
My guess is that deadlock detection in general is undecidable i.e. with more than one MVar present, but I may be wrong about that. Cheers Ben

On Tue, 12 May 2020 at 17:30, Henning Thielemann < lemming@henning-thielemann.de> wrote:
From your list of examples I deduce that the proposal is about programming errors. But we have HasCallStack for that one. How does the proposal improve or alter the HasCallStack solution? And how does it relate to the IO exception system with hierarchical exceptions and SomeException and so on?
As a parallel item, maybe it would be good if incomplete patterns could have a HasCallStack constraint so the current "Non-exaustive patterns in function foo" message could be extended with a helpful backtrace? If a programmer doesn't want this, then they could use complete matches?
participants (4)
-
Ben Franksen
-
Ben Gamari
-
Henning Thielemann
-
Tyson Whitehead