Skip to content

Commit 50c9d21

Browse files
authored
Adjust print_response to separate error-printing from result display, remove loop (#59218)
Took a stab at fixing #59209 , but it could be introducing other ways it could fail that I'm not appreciating? 1.11.4 logic: 1. If it's an error, print the error then break and return 2. If it's an error, and printing the error causes an error, catch it, try two levels of fallback printing, then break and return 3. If it's okay, display the result then break and return 4. If it's okay, and displaying the result causes an error, print a message, rethrow, catch, populate the response variables with the new exception info, and start the loop over to follow the error printing pathway for those values In no case does the loop execute more than twice. In 1.11.5+, condition 4 ends up following path 2, and path 4 would only be followed if there's an exception in the scaffolding around the `display` invocations. I restructured it to take out the loop, now it just attempts display if there was no error, accounts for errors during display, and then errors from either response or display are printed. I'm not sure if I used the `sigatomic_end` calls correctly. **EDIT: See comment below** Also tweaked the final fallback message because it suggests the issue is that the exception per se is a nested type, rather than that printing one exception is triggering another exception. And added a condition to trim REPL frames when it originates from within `print_response`. Fixes #59209
1 parent 920df7a commit 50c9d21

File tree

1 file changed

+47
-37
lines changed

1 file changed

+47
-37
lines changed

stdlib/REPL/src/REPL.jl

Lines changed: 47 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,11 @@ function print_response(repl::AbstractREPL, response, show_value::Bool, have_col
578578
return nothing
579579
end
580580

581-
function repl_display_error(errio::IO, @nospecialize errval)
581+
# N.B.: Any functions starting with __repl_entry cut off backtraces when printing in the REPL.
582+
__repl_entry_display(val) = Base.invokelatest(display, val)
583+
__repl_entry_display(specialdisplay::Union{AbstractDisplay,Nothing}, val) = Base.invokelatest(display, specialdisplay, val)
584+
585+
function __repl_entry_display_error(errio::IO, @nospecialize errval)
582586
# this will be set to true if types in the stacktrace are truncated
583587
limitflag = Ref(false)
584588
errio = IOContext(errio, :stacktrace_types_limited => limitflag)
@@ -593,53 +597,59 @@ end
593597
function print_response(errio::IO, response, backend::Union{REPLBackendRef,Nothing}, show_value::Bool, have_color::Bool, specialdisplay::Union{AbstractDisplay,Nothing}=nothing)
594598
Base.sigatomic_begin()
595599
val, iserr = response
596-
while true
600+
if !iserr
601+
# display result
597602
try
598-
Base.sigatomic_end()
599-
if iserr
600-
val = Base.scrub_repl_backtrace(val)
601-
Base.istrivialerror(val) || setglobal!(Base.MainInclude, :err, val)
602-
repl_display_error(errio, val)
603-
else
604-
if val !== nothing && show_value
605-
val2, iserr = if specialdisplay === nothing
606-
# display calls may require being run on the main thread
607-
call_on_backend(backend) do
608-
Base.invokelatest(display, val)
609-
end
610-
else
611-
call_on_backend(backend) do
612-
Base.invokelatest(display, specialdisplay, val)
613-
end
603+
if val !== nothing && show_value
604+
Base.sigatomic_end() # allow display to be interrupted
605+
val2, iserr = if specialdisplay === nothing
606+
# display calls may require being run on the main thread
607+
call_on_backend(backend) do
608+
__repl_entry_display(val)
614609
end
615-
if iserr
616-
println(errio, "Error showing value of type ", typeof(val), ":")
617-
throw(val2)
610+
else
611+
call_on_backend(backend) do
612+
__repl_entry_display(specialdisplay, val)
618613
end
619614
end
620-
end
621-
break
622-
catch ex
623-
if iserr
624-
println(errio) # an error during printing is likely to leave us mid-line
625-
println(errio, "SYSTEM (REPL): showing an error caused an error")
626-
try
627-
excs = Base.scrub_repl_backtrace(current_exceptions())
628-
setglobal!(Base.MainInclude, :err, excs)
629-
repl_display_error(errio, excs)
630-
catch e
631-
# at this point, only print the name of the type as a Symbol to
632-
# minimize the possibility of further errors.
615+
Base.sigatomic_begin()
616+
if iserr
633617
println(errio)
634-
println(errio, "SYSTEM (REPL): caught exception of type ", typeof(e).name.name,
635-
" while trying to handle a nested exception; giving up")
618+
println(errio, "Error showing value of type ", typeof(val), ":")
619+
val = val2
636620
end
637-
break
638621
end
622+
catch ex
623+
println(errio)
624+
println(errio, "SYSTEM (REPL): showing a value caused an error")
639625
val = current_exceptions()
640626
iserr = true
641627
end
642628
end
629+
if iserr
630+
# print error
631+
iserr = false
632+
while true
633+
try
634+
Base.sigatomic_end() # allow stacktrace printing to be interrupted
635+
val = Base.scrub_repl_backtrace(val)
636+
Base.istrivialerror(val) || setglobal!(Base.MainInclude, :err, val)
637+
__repl_entry_display_error(errio, val)
638+
break
639+
catch ex
640+
println(errio) # an error during printing is likely to leave us mid-line
641+
if !iserr
642+
println(errio, "SYSTEM (REPL): showing an error caused an error")
643+
val = current_exceptions()
644+
iserr = true
645+
else
646+
println(errio, "SYSTEM (REPL): caught exception of type ", typeof(ex).name.name,
647+
" while trying to print an exception; giving up")
648+
break
649+
end
650+
end
651+
end
652+
end
643653
Base.sigatomic_end()
644654
nothing
645655
end

0 commit comments

Comments
 (0)