Skip to content

Commit

Permalink
Add try/catch around handle_message() to catch errors during logging.
Browse files Browse the repository at this point in the history
Fixes #56889.

Before this PR, an exception thrown while constructing the objects to
log (the `msg`) would be caught and logged. However, an exception thrown
while _printing_ the msg to an IO would _not_ be caught, and can abort
the program. This breaks the promise that enabling verbose debug logging
shouldn't introduce new crashes.

After this PR, an exception thrown during handle_message is caught and
logged, just like an exception during `msg` construction:

```julia
julia> struct Foo end

julia> Base.show(::IO, ::Foo) = error("oh no")

julia> begin
           # Unexpectedly, the execption thrown while printing `Foo()` escapes
           @info Foo()
           # So we never reach this line! :'(
           println("~~~~~ ALL DONE ~~~~~~~~")
       end
┌ Error: Exception while generating log record in module Main at REPL[10]:3
│   exception =
│    oh no
│    Stacktrace:
│      [1] error(s::String)
│        @ Base ./error.jl:44
│      [2] show(::IOBuffer, ::Foo)
│        @ Main ./REPL[9]:1
...
│     [30] repl_main
│        @ ./client.jl:593 [inlined]
│     [31] _start()
│        @ Base ./client.jl:568
└ @ Main REPL[10]:3
~~~~~ ALL DONE ~~~~~~~~
```
  • Loading branch information
NHDaly committed Jan 9, 2025
1 parent 3d85309 commit 5c0ec7d
Showing 1 changed file with 12 additions and 1 deletion.
13 changes: 12 additions & 1 deletion base/logging/logging.jl
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ function logmsg_code(_module, file, line, level, message, exs...)
end
line = $(log_data._line)
local msg, kwargs
$(logrecord) && invokelatest($handle_message,
$(logrecord) && $handle_message_nothrow(
logger, level, msg, _module, group, id, file, line;
kwargs...)
end
Expand All @@ -420,6 +420,17 @@ function logmsg_code(_module, file, line, level, message, exs...)
end
end

@noinline function handle_message_nothrow(logger, level, msg, _module, group, id, file,
line, args...; kwargs...)
try
@invokelatest handle_message(
logger, level, msg, _module, group, id, file, line, args...;
kwargs...)
catch err
@invokelatest logging_error(logger, level, _module, group, id, file, line, err, true)
end
end

function process_logmsg_exs(_orig_module, _file, _line, level, message, exs...)
@nospecialize
local _group, _id
Expand Down

0 comments on commit 5c0ec7d

Please sign in to comment.