Skip to content

Commit d9b2922

Browse files
authored
show a nice stacktrace when breaking on error (#147)
add test
1 parent 804914a commit d9b2922

File tree

5 files changed

+115
-11
lines changed

5 files changed

+115
-11
lines changed

Manifest.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
4343

4444
[[JuliaInterpreter]]
4545
deps = ["CodeTracking", "InteractiveUtils", "Random", "UUIDs"]
46-
git-tree-sha1 = "0dd94cdd08c7250db6e023648cbec89674d422ca"
46+
git-tree-sha1 = "a1215f2d8fba52700b01fbe603e7e6b08eb7f305"
4747
repo-rev = "master"
4848
repo-url = "https://github.com/JuliaDebug/JuliaInterpreter.jl.git"
4949
uuid = "aa1ae85d-cabe-5617-a682-6adf51b2e16a"
50-
version = "0.3.0"
50+
version = "0.3.2"
5151

5252
[[LibGit2]]
5353
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"

src/commands.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@ function assert_allow_step(state)
1111
return true
1212
end
1313

14-
function show_breakpoint(io::IO, bp::BreakpointRef)
14+
function show_breakpoint(io::IO, bp::BreakpointRef, state::DebuggerState)
1515
outbuf = IOContext(IOBuffer(), io)
1616
if bp.err === nothing
1717
print(outbuf, "Hit breakpoint:\n")
1818
else
1919
print(outbuf, "Breaking for error:\n")
20-
Base.display_error(outbuf, bp.err, [])
20+
Base.display_error(outbuf, bp.err, state.frame)
21+
println(outbuf)
2122
end
2223
print(io, String(take!(outbuf.io)))
2324
end
@@ -37,7 +38,7 @@ function execute_command(state::DebuggerState, ::Union{Val{:c},Val{:nc},Val{:n},
3738
if pc isa BreakpointRef
3839
if pc.stmtidx != 0 # This is the dummy breakpoint to stop just after entering a call
3940
if state.terminal !== nothing # fix this, it happens when a test hits this and hasnt set a terminal
40-
show_breakpoint(Base.pipe_writer(state.terminal), pc)
41+
show_breakpoint(Base.pipe_writer(state.terminal), pc, state)
4142
end
4243
end
4344
if pc.err !== nothing

src/repl.jl

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,19 @@ function RunDebugger(frame, repl = nothing, terminal = nothing; initial_continue
5454
do_print_status = try
5555
execute_command(state, Val{Symbol(cmd1)}(), command)
5656
catch err
57-
# No point showing an internal stacktrace
58-
Base.display_error(Base.pipe_writer(terminal), err, [])
57+
# This will only show the stacktrae up to the current frame because
58+
# currently, the unwinding in JuliaInterpreter unlinks the frames to
59+
# where the error is thrown
60+
61+
# Buffer error printing
62+
io = IOContext(IOBuffer(), Base.pipe_writer(terminal))
63+
Base.display_error(io, err, JuliaInterpreter.leaf(state.frame))
64+
print(Base.pipe_writer(terminal), String(take!(io.io)))
65+
# Comment below out if you are debugging the Debugger
66+
# Base.display_error(Base.pipe_writer(terminal), err, catch_backtrace())
5967
LineEdit.transition(s, :abort)
6068
LineEdit.reset_state(s)
61-
return false
69+
return false
6270
end
6371
if old_level != state.level
6472
panel.prompt = promptname(state.level, "debug")
@@ -113,7 +121,15 @@ function RunDebugger(frame, repl = nothing, terminal = nothing; initial_continue
113121
panel.keymap_dict = LineEdit.keymap([repl_switch;state.standard_keymap])
114122

115123
if initial_continue
116-
execute_command(state, Val(:c), "c")
124+
try
125+
execute_command(state, Val(:c), "c")
126+
catch err
127+
# Buffer error printing
128+
io = IOContext(IOBuffer(), Base.pipe_writer(terminal))
129+
Base.display_error(io, err, JuliaInterpreter.leaf(state.frame))
130+
print(Base.pipe_writer(terminal), String(take!(io.io)))
131+
return
132+
end
117133
state.frame === nothing && return state.overall_result
118134
end
119135
print_status(Base.pipe_writer(terminal), active_frame(state); force_lowered=state.lowered_status)

test/ui.jl

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,14 @@ function f_end(x)
6565
end
6666
"we don't want to see this in the source code printing"
6767

68-
6968
@testset "UI" begin
7069
if Sys.isunix() && VERSION >= v"1.1.0"
7170
Debugger._print_full_path[] = false
7271
using TerminalRegressionTests
7372

7473
function run_terminal_test(frame, commands, validation)
7574
TerminalRegressionTests.automated_test(joinpath(@__DIR__, validation), commands) do emuterm
76-
#TerminalRegressionTests.create_automated_test(joinpath(@__DIR__, validation), commands) do emuterm
75+
#TerminalRegressionTests.create_automated_test(joinpath(@__DIR__, validation), commands) do emuterm
7776
repl = REPL.LineEditREPL(emuterm, true)
7877
repl.interface = REPL.setup_interface(repl)
7978
repl.specialdisplay = REPL.REPLDisplay(repl)
@@ -100,6 +99,12 @@ end
10099
["n\n", "n\n", "n\n"],
101100
"ui/history_floor.multiout")
102101

102+
Debugger.break_on(:error)
103+
run_terminal_test(@make_frame(error("foo")),
104+
["c\n", "bt\n", "q\n"],
105+
"ui/history_break_error.multiout")
106+
Debugger.break_off(:error)
107+
103108
if v"1.1">= VERSION < v"1.2"
104109
run_terminal_test(@make_frame(my_gcd_noinfo(10, 20)),
105110
["n\n","`", "a\n", UP_ARROW, UP_ARROW, CTRL_C, EOT],

test/ui/history_break_error.multiout

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
++++++++++++++++++++++++++++++++++++++++++++++++++
2+
|In error(s) at error.jl:33
3+
|>33 error(s::AbstractString) = throw(ErrorException(s))
4+
|
5+
|About to run: (ErrorException)("foo")
6+
|1|debug>
7+
--------------------------------------------------
8+
|AAAAAAAAAAAAAAAAAAAAAAAAAA
9+
|BBBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
10+
|
11+
|AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
12+
|CCCCCCCCC
13+
++++++++++++++++++++++++++++++++++++++++++++++++++
14+
|In error(s) at error.jl:33
15+
|>33 error(s::AbstractString) = throw(ErrorException(s))
16+
|
17+
|About to run: (ErrorException)("foo")
18+
|1|debug> c
19+
|Breaking for error:
20+
|ERROR: foo
21+
|Stacktrace:
22+
| [1] error(::String) at error.jl:33
23+
|
24+
|In error(s) at error.jl:33
25+
|>33 error(s::AbstractString) = throw(ErrorException(s))
26+
|
27+
|About to run: (throw)(ErrorException("foo"))
28+
|1|debug>
29+
--------------------------------------------------
30+
|AAAAAAAAAAAAAAAAAAAAAAAAAA
31+
|BBBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
32+
|
33+
|AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
34+
|CCCCCCCCCA
35+
|AAAAAAAAAAAAAAAAAAA
36+
|DDDDDDDDDD
37+
|EEEEEEEEEEE
38+
|EEEEEEEEEEEAAAAAAAAEAAAAEEEEEEEEEEE
39+
|
40+
|AAAAAAAAAAAAAAAAAAAAAAAAAA
41+
|BBBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
42+
|
43+
|AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
44+
|CCCCCCCCC
45+
++++++++++++++++++++++++++++++++++++++++++++++++++
46+
|In error(s) at error.jl:33
47+
|>33 error(s::AbstractString) = throw(ErrorException(s))
48+
|
49+
|About to run: (ErrorException)("foo")
50+
|1|debug> c
51+
|Breaking for error:
52+
|ERROR: foo
53+
|Stacktrace:
54+
| [1] error(::String) at error.jl:33
55+
|
56+
|In error(s) at error.jl:33
57+
|>33 error(s::AbstractString) = throw(ErrorException(s))
58+
|
59+
|About to run: (throw)(ErrorException("foo"))
60+
|1|debug> bt
61+
|[1] error(s) at error.jl:33
62+
| | s::String = "foo"
63+
|1|debug>
64+
--------------------------------------------------
65+
|AAAAAAAAAAAAAAAAAAAAAAAAAA
66+
|BBBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
67+
|
68+
|AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
69+
|CCCCCCCCCA
70+
|AAAAAAAAAAAAAAAAAAA
71+
|DDDDDDDDDD
72+
|EEEEEEEEEEE
73+
|EEEEEEEEEEEAAAAAAAAEAAAAEEEEEEEEEEE
74+
|
75+
|AAAAAAAAAAAAAAAAAAAAAAAAAA
76+
|BBBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
77+
|
78+
|AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
79+
|CCCCCCCCCAA
80+
|AAAAAAAAAAAAAAAAAAAAAAAAAAA
81+
|AAAAAAAAAAAAAAAAAAAAA
82+
|CCCCCCCCC

0 commit comments

Comments
 (0)