forked from mighty-gerbils/gerbil
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Debugging section of the hyperspec (mighty-gerbils#978)
This fleshes out the debugging section in the development section of the hyperspec and also makes sure `gerbil build --debug` works as advertised.
- Loading branch information
Showing
10 changed files
with
176 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,133 @@ | ||
# Debugging | ||
|
||
(TODO) | ||
Complex programs usually start as scribbling in a buffer, evaluated in | ||
the REPL. The scribbling then becomes a module, which later becomes a | ||
library, and eventually the program takes its more or less final | ||
shape. In the end, it is compiled as a fully static binary and shipped | ||
to a production server. | ||
|
||
See [debugging libraries](/reference/std/debug.md) for now. | ||
One thing is certain: in all stages of a program's evolution there | ||
will be bugs. Gerbil offers various mechanisms for debugging | ||
programs, from inception to production. | ||
|
||
See also [Testing](test.md). | ||
|
||
## Debugging in the REPL | ||
|
||
For interactive debugging, you can just load the relevant dynamic | ||
modules in the `gxi` REPL and utilize its facilities. If the module is | ||
loaded from source, then you will also get rudimentary stepping | ||
support. | ||
|
||
Here are the debugging commands avaiable in the `gxi` REPL: | ||
``` | ||
$ gxi | ||
Gerbil 0.17.0-336-g94ff9728 on Gambit v4.9.5-40-g24201248 | ||
> ,help | ||
Gambit v4.9.5-40-g24201248 | ||
,? | ,help : Summary of comma commands | ||
,h | ,(h X) : Help on procedure of last error or procedure/macro named X | ||
,q : Terminate the process | ||
,qt : Terminate the current thread | ||
,t : Jump to toplevel REPL | ||
,d : Jump to enclosing REPL | ||
,c | ,(c X) : Continue the computation with stepping off | ||
,s | ,(s X) : Continue the computation with stepping on (step) | ||
,l | ,(l X) : Continue the computation with stepping on (leap) | ||
,N : Move to specific continuation frame (N>=0) | ||
,N+ | ,N- : Move forward/backward by N continuation frames (N>=0) | ||
,+ | ,- : Like ,1+ and ,1- | ||
,++ | ,-- : Like ,N+ and ,N- with N = nb. of frames at head of backtrace | ||
,y : Display one-line summary of current frame | ||
,i : Display procedure attached to current frame | ||
,b | ,(b X) : Display backtrace of current continuation or X (cont/thread) | ||
,be | ,(be X) : Like ,b and ,(b X) but also display environment | ||
,bed | ,(bed X) : Like ,be and ,(be X) but also display dynamic environment | ||
,e | ,(e X) : Display environment of current frame or X (proc/cont/thread) | ||
,ed | ,(ed X) : Like ,e and ,(e X) but also display dynamic environment | ||
,st | ,(st X) : Display current thread group, or X (thread/thread group) | ||
,(v X) : Start a REPL visiting X (proc/cont/thread) | ||
``` | ||
|
||
See also the [Interactive Gerbil Shell](/guide/shell.md) page for some | ||
utilities useful for debugging in the REPL. | ||
|
||
## Debugging with Exception Stack Traces | ||
|
||
Gerbil goes to a lot of effort to ensure all exceptions have full | ||
stack traces and a proper error context pointing to the location of | ||
the source code where the fault condition occured. | ||
|
||
If you have an exception stack trace, you can navigate to the | ||
offending code in `GERBIL_PREFIX/src` and understand what the problem | ||
is. Once you understand it, you can dynamically load the module where | ||
the fault originated in the `gxi` REPL to reproduce and fix the | ||
issue. Once the issue is fixed, you should probably add a regression | ||
test as well. | ||
|
||
## Debugging Hard Crashes | ||
|
||
Occasionally, if you are using a `(not safe)` declaration in some | ||
performance critical piece of code, there can be segfaults. All the | ||
standard Gerbil modules included in `libgerbil` have debug symbols | ||
enabled, so you can just run the program in gdb and get the location | ||
of the crash. | ||
|
||
If the crash is inside `libgerbil`, then you will most like have exact | ||
location pointing to the _expanded_ source of the crash. You can find | ||
the offending code in `GERBIL_PREFIX/lib/static`. Note that we | ||
_could_ have the tracked scheme source point to the original, | ||
unexpanded source, but we prefer to work with expanded source as we'd | ||
like to see the actual code that was compiled and also have the | ||
ability to debug potential compiler bugs (these are exceedingly rare, | ||
but they can happen). | ||
|
||
If the crash is inside your own library or main code and you have an | ||
input repro, you can just load the executable module of your program | ||
dynamically with `gerbil :your-executable-module input-param | ||
...`. | ||
So within gdb, you can `gdb gerbil` and `r :your-executable-module input-param`. | ||
This will get you source location, as all dynamically executable | ||
modules are compiled with debug symbols. | ||
|
||
If the crash is non deterministic, you can build your executable with | ||
`gerbil build --debug`. This will get you debug symbols for the binary | ||
and you can just run it directly with gdb until the crash occurs. The | ||
actual expanded source files will be in your build's | ||
`GERBIL_PATH/lib/static`. So if you built your project with `gerbil | ||
build --debug`, these will be located in `.gerbil/lib/static`. | ||
|
||
::: warning Note | ||
Sometimes you might get a crash that has no usable stack trace. This | ||
can occur if you are calling a non procedure in unsafe context or | ||
because of some very low level bugs. If that happens, you will need | ||
to guess a bit where the crash is coming from and disable your `(not | ||
safe)` declarations in the relevant module so that you get an | ||
exception with a stack trace instead. | ||
|
||
If you determine that such a crash occurs because of some low level | ||
Gerbil or Gambit bug, please file an [Issue](https://github.com/mighty-gerbils/gerbil/issues) | ||
and/or get in touch with the Gerbil development team on | ||
[gitter](https://gitter.im/gerbil-scheme/community). | ||
::: | ||
|
||
|
||
## Debugging Live Programs | ||
|
||
You can use a remote/network REPL to connect to a running program | ||
and evaluate code that helps you inspect and modify the state of | ||
the program. | ||
|
||
Gerbil offers a couple of different options for this: | ||
- The embedded [Network REPL](/reference/std/net/repl.md) is useful for any | ||
running program in your development workstation or laptop. | ||
You can just use `telnet` to connect, but you have to | ||
manually start the repl server inside your program. | ||
- Servers in an [Actor Ensemble](/tutorials/ensemble.md) automatically have | ||
network repl capabilities for debugging and loading code. | ||
You can interact with them using the `gxensemble` tool. | ||
|
||
Once you have a REPL to a running program, you can interact with it by | ||
evaluating code. Gerbil also provides some useful | ||
[debugging libraries](/reference/std/debug.md) you can use to inspect the | ||
state of the program, debug memory usage and leaks, and so on. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters