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


_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

Reply via email to