failure implementing :next command in ghci

Peter Hercek phercek at
Sun Apr 12 13:26:23 EDT 2009


So I wanted to give implementing :next ghci debugger command a shot. It 
looked easy and I could use it. Moreover it would give me an easy way to 
implement dynamic stack in ghci (using similar approach as used for 
trace) ... well if I would feel like that since I was a bit discouraged 
about it. The problem is I failed miserably. I still think it is easy to 
do. I just do not know how to create correct arguments for 
rts_breakpoint_io_action and I have given up finding up myself for now.

The proposed meaning for :next

Lets mark dynamic stack size at a breakpoint (at which we issue :next) 
as breakStackSize and its selected expression as breakSpan. Then :next 
would single step till any of these is true:
1) current dynamic stack size is smaller than breakStackSize
2) current dynamic stack size is equal to breakStackSize and the current 
selected expression is not a subset of breakSpan

I hope the above would make good sense but I do not really know since 
maybe rts does some funny things with stack sometimes. If you think the 
proposed behavior is garbage let me know why so that I do not waste more 
time with this :)

Ok, lets get back to why I failed. I think anybody who knows rts well 
could probably tell me what's wrong in few minutes. The patch 
representing my attempt is attached. It is done against the latest ghc 
(head branch). I want to add stack size as the last argument of 
rts_breakpoint_io_action so its signature would change from:
Bool -> BreakInfo -> HValue -> IO ()
Bool -> BreakInfo -> HValue -> Int -> IO ()

Since dynamic stack is continuous I can find out stack size easily. I 
did not implemented this yet, as well I did not implement this at all 
for exceptions. The only thing I cared for now is passing one more 
integer to rts_breakpoint_io_action. The argument contains only zero now 
but that should be enough to see if I can add one more argument.
I tested it by loading this source code to ghci:
f :: Int -> Int
f x = x + 1
a = f 1

... then I used ":break f" and ":force a" in ghci to see whether I can 
pass the new argument correctly. This test works since I added printing 
of the last argument (the wanna be stack size) in
noBreakAction :: Bool -> BreakInfo -> HValue -> Int -> IO ()
noBreakAction False _ _ x = putStrLn $ "*** Ignoring breakpoint " ++ show x
noBreakAction True  _ _ _ = return () -- exception: just continue

The noBreakAction implementation is just a test for now. Unfortunately 
when I force the last argument  it crashes. I think it is because I do 
not create the closure for it correctly in the code for bci_BRK_FUN in 
rts/Interpreter.c. Can somebody tell me what is wrong there or where to 
find more information about how to fill in the stack with 
rts_breakpoint_io_action arguments correctly?

Also, any information somewhere about where to use allocate and where to 
use allocateLocal? I was surprised a bit that interpretBCO uses allocate 
much but no allocateLocal which is supposed to be quicker for a single 

I skimmed all of ghc commentary and read the pages which looked related 
carefully but either it is not there or I missed it :-(

-------------- next part --------------
A non-text attachment was scrubbed...
Name: stackSize.patch
Type: text/x-patch
Size: 6642 bytes
Desc: not available
Url :

More information about the Glasgow-haskell-users mailing list