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:
_______________________________________________ ghc-devs mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs |
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:
_______________________________________________ ghc-devs mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs |
On Fri, May 8, 2020 at 9:32 AM Carter Schonwald <[hidden email]> wrote:
_______________________________________________ ghc-devs mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs |
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 |
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 |
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)? 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 |
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? 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 |
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 |
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 |
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 |
Free forum by Nabble | Edit this page |