Skip to content

Commit

Permalink
Restore StackOverflow error message for repeated frames
Browse files Browse the repository at this point in the history
Fixes backtrace printing to display the number of times a frame is
repeated, if there is a frame that's duplicated several times.

```julia
julia> function foo() foo() end
foo (generic function with 1 method)

julia> foo()
ERROR: StackOverflowError:
Stacktrace:
 [1] foo() (repeats 79984 times)
   @ Main ./REPL[16]:1
```

Fixes JuliaLang#37587.
  • Loading branch information
NHDaly committed Jan 24, 2021
1 parent 69d2453 commit 8bed145
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 7 deletions.
13 changes: 6 additions & 7 deletions base/errorshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -573,17 +573,17 @@ stacktrace_linebreaks()::Bool =
tryparse(Bool, get(ENV, "JULIA_STACKTRACE_LINEBREAKS", "false")) === true

function show_full_backtrace(io::IO, trace::Vector; print_linebreaks::Bool)
n = length(trace)
ndigits_max = ndigits(n)
num_frames = length(trace)
ndigits_max = ndigits(num_frames)

modulecolordict = copy(STACKTRACE_FIXEDCOLORS)
modulecolorcycler = Iterators.Stateful(Iterators.cycle(STACKTRACE_MODULECOLORS))

println(io, "\nStacktrace:")

for (i, frame) in enumerate(trace)
print_stackframe(io, i, frame, 1, ndigits_max, modulecolordict, modulecolorcycler)
if i < n
for (i, (frame, n)) in enumerate(trace)
print_stackframe(io, i, frame, n, ndigits_max, modulecolordict, modulecolorcycler)
if i < num_frames
println(io)
print_linebreaks && println(io)
end
Expand Down Expand Up @@ -782,8 +782,7 @@ function show_backtrace(io::IO, t::Vector)

try invokelatest(update_stackframes_callback[], filtered) catch end
# process_backtrace returns a Vector{Tuple{Frame, Int}}
frames = map(x->first(x)::StackFrame, filtered)
show_full_backtrace(io, frames; print_linebreaks = stacktrace_linebreaks())
show_full_backtrace(io, filtered; print_linebreaks = stacktrace_linebreaks())
return
end

Expand Down
25 changes: 25 additions & 0 deletions test/errorshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,7 @@ end
@test getline(outputc) == getline(output0) + 2
end


# issue #30633
@test_throws ArgumentError("invalid index: \"foo\" of type String") [1]["foo"]
@test_throws ArgumentError("invalid index: nothing of type Nothing") [1][nothing]
Expand Down Expand Up @@ -763,3 +764,27 @@ let err = nothing
@test !occursin("2d", err_str)
end
end

single_repeater() = single_repeater()
pair_repeater_a() = pair_repeater_b()
pair_repeater_b() = pair_repeater_a()

@testset "repeated stack frames" begin
let bt = try single_repeater()
catch
catch_backtrace()
end
bt_str = sprint(Base.show_backtrace, bt)
m = @__MODULE__
@test occursin(r"repeats \d+ times", bt_str)
end

let bt = try pair_repeater_a()
catch
catch_backtrace()
end
bt_str = sprint(Base.show_backtrace, bt)
m = @__MODULE__
@test occursin(r"the last 2 lines are repeated \d+ more times", bt_str)
end
end

0 comments on commit 8bed145

Please sign in to comment.