Re: Status of stack trace work

2012-11-08 Thread Simon Marlow

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


Re: Using DeepSeq for exception ordering

2012-11-08 Thread Simon Hengel
Hi Edward,
thanks a lot for your reply.

 rnf can be thought of a function which produces a thunk (for unit)
 which, when forced, fully evaluates the function.  With this in hand,
 it's pretty clear how to use evaluate to enforce ordering:
 
 evaluate (rnf ('a': throw exceptionA))

So if I understand correctly, then if I have

  evaluate (x_1 `seq` x_2 `seq` x_3 `seq` ... `seq` x_n)
  throwIO exceptionB

it is guaranteed that exceptionB can only happens if none of the xs are
exceptional.

I was just going to say that I can give at least one counterexample
where this does not hold:

  evaluate (('a' : undefined) `deepseq` return () :: IO ())
  throwIO exceptionB

But then I realized that here exceptionA is optimized away altogether.
For me this smells like a bug.  Is this related to [1]?

Cheers,
Simon

[1] http://hackage.haskell.org/trac/ghc/ticket/2273

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


Re: Using DeepSeq for exception ordering

2012-11-08 Thread Albert Y. C. Lai

On 12-11-08 07:12 AM, Simon Hengel wrote:

I was just going to say that I can give at least one counterexample
where this does not hold:

   evaluate (('a' : undefined) `deepseq` return () :: IO ())
   throwIO exceptionB

But then I realized that here exceptionA is optimized away altogether.
For me this smells like a bug.  Is this related to [1]?

[1] http://hackage.haskell.org/trac/ghc/ticket/2273


Interesting. A few more tests (all GHC 7.4.2, linux, x86 32-bit, use 
ghc -O to compile):


The following cases throw A:

import Control.DeepSeq
import Control.Exception

main = do
  evaluate (('a' : error A) `deepseq` return () :: Maybe ())
  throwIO (userError B)

main = do
  evaluate (('a' : error A) `deepseq` ())
  throwIO (userError B)

main = do
  evaluate (('a' : error A) `deepseq` True)
  throwIO (userError B)

main = do
  x - evaluate (('a' : error A) `deepseq` putStrLn hi)
  x
  throwIO (userError B)

The following cases throw B:

main = do
  evaluate (('a' : error A) `deepseq` return () :: IO ())
  throwIO (userError B)

main = do
  evaluate (('a' : error A) `deepseq` putStrLn hi)
  throwIO (userError B)

main = do
  evaluate (('a' : error A) `deepseq` getLine)
  throwIO (userError B)

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


Re: Using DeepSeq for exception ordering

2012-11-08 Thread Nicolas Frisby
And the important observation is: all of them throw A if interpreted in
ghci or compiled without -O, right?


On Thu, Nov 8, 2012 at 11:24 AM, Albert Y. C. Lai tre...@vex.net wrote:

 On 12-11-08 07:12 AM, Simon Hengel wrote:

 I was just going to say that I can give at least one counterexample
 where this does not hold:

evaluate (('a' : undefined) `deepseq` return () :: IO ())
throwIO exceptionB

 But then I realized that here exceptionA is optimized away altogether.
 For me this smells like a bug.  Is this related to [1]?

 [1] 
 http://hackage.haskell.org/**trac/ghc/ticket/2273http://hackage.haskell.org/trac/ghc/ticket/2273


 Interesting. A few more tests (all GHC 7.4.2, linux, x86 32-bit, use ghc
 -O to compile):

 The following cases throw A:

 import Control.DeepSeq
 import Control.Exception

 main = do
   evaluate (('a' : error A) `deepseq` return () :: Maybe ())
   throwIO (userError B)

 main = do
   evaluate (('a' : error A) `deepseq` ())
   throwIO (userError B)

 main = do
   evaluate (('a' : error A) `deepseq` True)
   throwIO (userError B)

 main = do
   x - evaluate (('a' : error A) `deepseq` putStrLn hi)
   x
   throwIO (userError B)

 The following cases throw B:

 main = do
   evaluate (('a' : error A) `deepseq` return () :: IO ())
   throwIO (userError B)

 main = do
   evaluate (('a' : error A) `deepseq` putStrLn hi)
   throwIO (userError B)

 main = do
   evaluate (('a' : error A) `deepseq` getLine)
   throwIO (userError B)


 __**_
 Glasgow-haskell-users mailing list
 Glasgow-haskell-users@haskell.**org Glasgow-haskell-users@haskell.org
 http://www.haskell.org/**mailman/listinfo/glasgow-**haskell-usershttp://www.haskell.org/mailman/listinfo/glasgow-haskell-users

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


Re: Using DeepSeq for exception ordering

2012-11-08 Thread Albert Y. C. Lai

On 12-11-08 01:01 PM, Nicolas Frisby wrote:

And the important observation is: all of them throw A if interpreted in
ghci or compiled without -O, right?


Yes.

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


Re: Using DeepSeq for exception ordering

2012-11-08 Thread Edward Z. Yang
It looks like the optimizer is getting confused when the value being
evaluated is an IO action (nota bene: 'evaluate m' where m :: IO a
is pretty odd, as far as things go). File a bug?

Cheers,
Edward

Excerpts from Albert Y. C. Lai's message of Thu Nov 08 10:04:15 -0800 2012:
 On 12-11-08 01:01 PM, Nicolas Frisby wrote:
  And the important observation is: all of them throw A if interpreted in
  ghci or compiled without -O, right?
 
 Yes.
 

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


Re: Using DeepSeq for exception ordering

2012-11-08 Thread Antoine Latter
Is this related to imprecise exceptions?

http://research.microsoft.com/en-us/um/people/simonpj/papers/imprecise-exn.htm

Antoine


On Thu, Nov 8, 2012 at 12:01 PM, Nicolas Frisby nicolas.fri...@gmail.comwrote:

 And the important observation is: all of them throw A if interpreted in
 ghci or compiled without -O, right?


 On Thu, Nov 8, 2012 at 11:24 AM, Albert Y. C. Lai tre...@vex.net wrote:

 On 12-11-08 07:12 AM, Simon Hengel wrote:

 I was just going to say that I can give at least one counterexample
 where this does not hold:

evaluate (('a' : undefined) `deepseq` return () :: IO ())
throwIO exceptionB

 But then I realized that here exceptionA is optimized away altogether.
 For me this smells like a bug.  Is this related to [1]?

 [1] 
 http://hackage.haskell.org/**trac/ghc/ticket/2273http://hackage.haskell.org/trac/ghc/ticket/2273


 Interesting. A few more tests (all GHC 7.4.2, linux, x86 32-bit, use ghc
 -O to compile):

 The following cases throw A:

 import Control.DeepSeq
 import Control.Exception

 main = do
   evaluate (('a' : error A) `deepseq` return () :: Maybe ())
   throwIO (userError B)

 main = do
   evaluate (('a' : error A) `deepseq` ())
   throwIO (userError B)

 main = do
   evaluate (('a' : error A) `deepseq` True)
   throwIO (userError B)

 main = do
   x - evaluate (('a' : error A) `deepseq` putStrLn hi)
   x
   throwIO (userError B)

 The following cases throw B:

 main = do
   evaluate (('a' : error A) `deepseq` return () :: IO ())
   throwIO (userError B)

 main = do
   evaluate (('a' : error A) `deepseq` putStrLn hi)
   throwIO (userError B)

 main = do
   evaluate (('a' : error A) `deepseq` getLine)
   throwIO (userError B)


 __**_
 Glasgow-haskell-users mailing list
 Glasgow-haskell-users@haskell.**org Glasgow-haskell-users@haskell.org
 http://www.haskell.org/**mailman/listinfo/glasgow-**haskell-usershttp://www.haskell.org/mailman/listinfo/glasgow-haskell-users



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


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