From 8bed145e0e91f03b0ab9fdbc44cfbdda4a44cd06 Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Sat, 23 Jan 2021 20:53:52 -0500 Subject: [PATCH] Restore StackOverflow error message for repeated frames 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 #37587. --- base/errorshow.jl | 13 ++++++------- test/errorshow.jl | 25 +++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/base/errorshow.jl b/base/errorshow.jl index 50325be8354e5..2d7a81b0ccf63 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -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 @@ -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 diff --git a/test/errorshow.jl b/test/errorshow.jl index 30c7d61bdadde..6ecb529cf3f5f 100644 --- a/test/errorshow.jl +++ b/test/errorshow.jl @@ -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] @@ -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