From 8bed145e0e91f03b0ab9fdbc44cfbdda4a44cd06 Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Sat, 23 Jan 2021 20:53:52 -0500 Subject: [PATCH 1/5] 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 From b2ad4d7fca0a8681d3c3b8df2ec9253412638a78 Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Thu, 18 Feb 2021 21:45:19 -0500 Subject: [PATCH 2/5] Clean up test/errorshow.jl - remove accidental cruft line --- test/errorshow.jl | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/errorshow.jl b/test/errorshow.jl index 6ecb529cf3f5f..22ccb4996126c 100644 --- a/test/errorshow.jl +++ b/test/errorshow.jl @@ -775,7 +775,6 @@ pair_repeater_b() = pair_repeater_a() catch_backtrace() end bt_str = sprint(Base.show_backtrace, bt) - m = @__MODULE__ @test occursin(r"repeats \d+ times", bt_str) end @@ -784,7 +783,6 @@ pair_repeater_b() = pair_repeater_a() 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 From df0e968bc6e36906da331513dfa14be07e69e392 Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Thu, 18 Feb 2021 21:45:59 -0500 Subject: [PATCH 3/5] Add debugging print lines: print backtrace length --- test/errorshow.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/errorshow.jl b/test/errorshow.jl index 22ccb4996126c..aff2b76d0afcb 100644 --- a/test/errorshow.jl +++ b/test/errorshow.jl @@ -772,6 +772,7 @@ pair_repeater_b() = pair_repeater_a() @testset "repeated stack frames" begin let bt = try single_repeater() catch + println("length: ", length(catch_backtrace())) catch_backtrace() end bt_str = sprint(Base.show_backtrace, bt) @@ -780,6 +781,7 @@ pair_repeater_b() = pair_repeater_a() let bt = try pair_repeater_a() catch + println("length: ", length(catch_backtrace())) catch_backtrace() end bt_str = sprint(Base.show_backtrace, bt) From 89911f8797292b9d378afe87ad43872de87c19b8 Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Thu, 18 Feb 2021 21:46:58 -0500 Subject: [PATCH 4/5] Revert "Add debugging print lines: print backtrace length" This reverts commit df0e968bc6e36906da331513dfa14be07e69e392. --- test/errorshow.jl | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/errorshow.jl b/test/errorshow.jl index aff2b76d0afcb..22ccb4996126c 100644 --- a/test/errorshow.jl +++ b/test/errorshow.jl @@ -772,7 +772,6 @@ pair_repeater_b() = pair_repeater_a() @testset "repeated stack frames" begin let bt = try single_repeater() catch - println("length: ", length(catch_backtrace())) catch_backtrace() end bt_str = sprint(Base.show_backtrace, bt) @@ -781,7 +780,6 @@ pair_repeater_b() = pair_repeater_a() let bt = try pair_repeater_a() catch - println("length: ", length(catch_backtrace())) catch_backtrace() end bt_str = sprint(Base.show_backtrace, bt) From dced572cb9c69bc718dc129bf7fff720ef00acfd Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Mon, 22 Feb 2021 15:36:43 -0500 Subject: [PATCH 5/5] Disable repeated stack frames tests on non-macOS --- test/errorshow.jl | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/test/errorshow.jl b/test/errorshow.jl index 22ccb4996126c..0fdc13ea0d9fe 100644 --- a/test/errorshow.jl +++ b/test/errorshow.jl @@ -765,24 +765,26 @@ let err = nothing 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() +if Sys.isapple() # The "repeated stack frames" formatting currently only works on MacOS. + 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) + @test occursin(r"repeats \d+ times", bt_str) end - bt_str = sprint(Base.show_backtrace, bt) - @test occursin(r"repeats \d+ times", bt_str) - end - let bt = try pair_repeater_a() - catch - catch_backtrace() + let bt = try pair_repeater_a() + catch + catch_backtrace() + end + bt_str = sprint(Base.show_backtrace, bt) + @test occursin(r"the last 2 lines are repeated \d+ more times", bt_str) end - bt_str = sprint(Base.show_backtrace, bt) - @test occursin(r"the last 2 lines are repeated \d+ more times", bt_str) end -end +end # Sys.isapple()