Status of stack trace work
Simon Marlow
marlowsd at gmail.com
Thu Nov 8 12:13:46 CET 2012
On 08/11/12 05:43, Johan Tibell wrote:
> I can't wait until we have some for of stack traces in GHC. What's the
> current status? Did the semantics you presented at HIW12 work out? Even
> though the full bells and whistles of full stack traces is something I'd
> really like to see, even their more impoverished cousins, the lexical
> stack trace, would be helpful in tracking down just which call to head
> gave rise to a "head: empty" list error.
The profiler currently uses the stack tracing scheme I described in that
talk, and you can use it to chase "head []" right now (with +RTS -xc).
You can also use the GHC.Stack.errorWithStackTrace function that I
demonstrated in the talk; I added it to GHC.Stack after 7.6.1, but the
code should work with 7.6.1 if you import GHC.Stack:
-- | Like the function 'error', but appends a stack trace to the error
-- message if one is available.
errorWithStackTrace :: String -> a
errorWithStackTrace x = unsafeDupablePerformIO $ do
stack <- ccsToStrings =<< getCurrentCCS x
if null stack
then throwIO (ErrorCall x)
else throwIO (ErrorCall (x ++ '\n' : renderStack stack))
I realise that compiling with profiling is not always practical, and not
as immediate as we'd like, and also it doesn't work in GHCi. What I
think we should do is
(a) add stack trace support to GHCi, so we would get stack traces
for interpreted code
(b) incorporate the work of Peter Wortmann and Nathan Howell to get
DWARF information into GHC binaries, and use this to get
execution stacks without needing to compile for profiling
I'd love to see people working on (b) especially, and I'll be happy to
provide direction or pointers to anyone who's interested (I'm no DWARF
expert though). The stacks you get this way won't be as nice as the
ones we get from the profiler, and there will be absolutely no
guarantees about the quality of the information, or even that you'll get
the same stack with -O as you get without. But some information is
better than no information for debugging purposes.
> Once we do have some sort of stack traces, could we have throw
> automatically attach it to the exception, so we can get a printed stack
> trace upon crash? Is that how e.g. Java deals with that? Will that make
> other uses of exceptions (such as throwing async exceptions to kill
> threads) get much more expensive if we try to attach stack traces? A
> frequent user of async exceptions are web servers that start a timeout
> call per request.
One way to do this is to provide a variant of catch that grabs the stack
trace, e.g.
catchStack :: Exception e => IO a -> (e -> Stack -> IO a) -> IO a
and this could be implemented cheaply, because the stack only needs to
be constructed when it is being caught by catchStack. However, this
doesn't work well when an exception is rethrown, such as when it passes
through a nest of brackets. To make that work, you really have to
attach the stack trace to the exception. We could change our
SomeException type to include a stack trace, and that would be fairly
cheap to use with profiling (because capturing the current stack is
free), but it would be more expensive with DWARF stacks so you'd want a
runtime option to enable it.
Cheers,
Simon
More information about the Glasgow-haskell-users
mailing list