Skip to content
This repository was archived by the owner on Apr 12, 2019. It is now read-only.

Commit ba209d5

Browse files
LiozouStefanKarpinski
authored andcommitted
Fixed long stacktrace printing (JuliaLang#28453)
1 parent 27f7a74 commit ba209d5

File tree

2 files changed

+41
-12
lines changed

2 files changed

+41
-12
lines changed

base/errorshow.jl

+26-12
Original file line numberDiff line numberDiff line change
@@ -458,17 +458,18 @@ function show_method_candidates(io::IO, ex::MethodError, @nospecialize kwargs=()
458458
end
459459
end
460460

461+
# Contains file name and file number. Gets set when a backtrace
462+
# or methodlist is shown. Used by the REPL to make it possible to open
463+
# the location of a stackframe/method in the editor.
464+
global LAST_SHOWN_LINE_INFOS = Tuple{String, Int}[]
465+
461466
function show_trace_entry(io, frame, n; prefix = "")
467+
push!(LAST_SHOWN_LINE_INFOS, (string(frame.file), frame.line))
462468
print(io, "\n", prefix)
463469
show(io, frame, full_path=true)
464470
n > 1 && print(io, " (repeats ", n, " times)")
465471
end
466472

467-
# Contains file name and file number. Gets set when a backtrace
468-
# or methodlist is shown. Used by the REPL to make it possible to open
469-
# the location of a stackframe/method in the editor.
470-
global LAST_SHOWN_LINE_INFOS = Tuple{String, Int}[]
471-
472473
# In case the line numbers in the source code have changed since the code was compiled,
473474
# allow packages to set a callback function that corrects them.
474475
# (Used by Revise and perhaps other packages.)
@@ -489,6 +490,10 @@ function show_reduced_backtrace(io::IO, t::Vector, with_prefix::Bool)
489490
frame appears just before. =#
490491

491492
displayed_stackframes = []
493+
repeated_cycle = Tuple{Int,Int,Int}[]
494+
# First: line to introuce the "cycle repetition" message
495+
# Second: length of the cycle
496+
# Third: number of repetitions
492497
frame_counter = 1
493498
while frame_counter < length(t)
494499
(last_frame, n) = t[frame_counter]
@@ -507,11 +512,10 @@ function show_reduced_backtrace(io::IO, t::Vector, with_prefix::Bool)
507512
while i < length(t) && t[i] == t[j]
508513
i+=1 ; j+=1
509514
end
510-
if j >= frame_counter
515+
if j >= frame_counter-1
511516
#= At least one cycle repeated =#
512517
repetitions = div(i - frame_counter + 1, cycle_length)
513-
print(io, "\n ... (the last ", cycle_length, " lines are repeated ",
514-
repetitions, " more time", repetitions>1 ? "s)" : ")")
518+
push!(repeated_cycle, (length(displayed_stackframes), cycle_length, repetitions))
515519
frame_counter += cycle_length * repetitions - 1
516520
break
517521
end
@@ -524,13 +528,24 @@ function show_reduced_backtrace(io::IO, t::Vector, with_prefix::Bool)
524528

525529
try invokelatest(update_stackframes_callback[], displayed_stackframes) catch end
526530

527-
for (frame, n) in displayed_stackframes
531+
push!(repeated_cycle, (0,0,0)) # repeated_cycle is never empty
532+
frame_counter = 1
533+
for i in 1:length(displayed_stackframes)
534+
(frame, n) = displayed_stackframes[i]
528535
if with_prefix
529-
show_trace_entry(io, frame, n, prefix = string(" [", frame_counter-1, "] "))
530-
push!(LAST_SHOWN_LINE_INFOS, (string(frame.file), frame.line))
536+
show_trace_entry(io, frame, n, prefix = string(" [", frame_counter, "] "))
531537
else
532538
show_trace_entry(io, frame, n)
533539
end
540+
while repeated_cycle[1][1] == i # never empty because of the initial (0,0,0)
541+
cycle_length = repeated_cycle[1][2]
542+
repetitions = repeated_cycle[1][3]
543+
popfirst!(repeated_cycle)
544+
print(io, "\n ... (the last ", cycle_length, " lines are repeated ",
545+
repetitions, " more time", repetitions>1 ? "s)" : ")")
546+
frame_counter += cycle_length * repetitions
547+
end
548+
frame_counter += 1
534549
end
535550
end
536551

@@ -555,7 +570,6 @@ function show_backtrace(io::IO, t::Vector)
555570
for (last_frame, n) in filtered
556571
frame_counter += 1
557572
show_trace_entry(IOContext(io, :backtrace => true), last_frame, n, prefix = string(" [", frame_counter, "] "))
558-
push!(LAST_SHOWN_LINE_INFOS, (string(last_frame.file), last_frame.line))
559573
end
560574
return
561575
end

test/errorshow.jl

+15
Original file line numberDiff line numberDiff line change
@@ -521,3 +521,18 @@ end
521521
end
522522
end
523523

524+
# issue #28442
525+
@testset "Long stacktrace printing" begin
526+
f28442(c) = g28442(c + 1)
527+
g28442(c) = c > 10000 ? (return backtrace()) : f28442(c+1)
528+
bt = f28442(1)
529+
io = IOBuffer()
530+
Base.show_backtrace(io, bt)
531+
output = split(String(take!(io)), '\n')
532+
@test output[3][1:4] == " [1]"
533+
@test occursin("g28442", output[3])
534+
@test output[4][1:4] == " [2]"
535+
@test occursin("f28442", output[4])
536+
@test occursin("the last 2 lines are repeated 5000 more times", output[5])
537+
@test output[6][1:8] == " [10003]"
538+
end

0 commit comments

Comments
 (0)