Skip to content

Commit 5ac3e7b

Browse files
committed
Fix logger crash when :gen_statem format_status/3 does not return a tuple
1 parent 0df128c commit 5ac3e7b

File tree

2 files changed

+63
-6
lines changed

2 files changed

+63
-6
lines changed

lib/logger/lib/logger/translator.ex

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ defmodule Logger.Translator do
298298
client_info: client,
299299
name: name,
300300
reason: {kind, reason, stack},
301-
state: {state, data},
301+
state: state,
302302
queue: queue,
303303
postponed: postponed,
304304
callback_mode: callback_mode,
@@ -324,12 +324,19 @@ defmodule Logger.Translator do
324324
["\nPostponed: #{inspect(postponed, inspect_opts)}"]
325325

326326
if min_level == :debug do
327+
state_info =
328+
case state do
329+
{state, data} ->
330+
["\nState: ", inspect(state, inspect_opts), "\nData: ", inspect(data, inspect_opts)]
331+
332+
# might be formatted by c:format_status/3
333+
state ->
334+
["\nState: ", inspect(state, inspect_opts)]
335+
end
336+
327337
msg = [
328338
msg,
329-
"\nState: ",
330-
inspect(state, inspect_opts),
331-
"\nData: ",
332-
inspect(data, inspect_opts),
339+
state_info,
333340
"\nCallback mode: ",
334341
"#{inspect(callback_mode, inspect_opts)}, state_enter: #{state_enter?}"
335342
| format_client_info(client)

lib/logger/test/logger/translator_test.exs

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,28 @@ defmodule Logger.TranslatorTest do
100100
end
101101
end
102102

103+
defmodule MyGenStatemFormatStatus do
104+
@behaviour :gen_statem
105+
106+
@impl true
107+
def callback_mode, do: :handle_event_function
108+
109+
@impl true
110+
def init(state) do
111+
{:ok, :no_state, state}
112+
end
113+
114+
@impl true
115+
def handle_event({:call, _}, :error, :no_state, _data) do
116+
raise "oops"
117+
end
118+
119+
@impl :gen_statem
120+
def format_status(_opts, [_pdict, _, state]) do
121+
state
122+
end
123+
end
124+
103125
defmodule MyBridge do
104126
@behaviour :supervisor_bridge
105127

@@ -393,7 +415,7 @@ defmodule Logger.TranslatorTest do
393415
assert {%RuntimeError{message: "oops"}, [_ | _]} = process_metadata[:crash_reason]
394416

395417
refute Map.has_key?(gen_statem_metadata, :initial_call)
396-
assert process_metadata[:initial_call] == {Logger.TranslatorTest.MyGenStatem, :init, 1}
418+
assert process_metadata[:initial_call] == {MyGenStatem, :init, 1}
397419

398420
refute Map.has_key?(gen_statem_metadata, :registered_name)
399421
refute Map.has_key?(process_metadata, :registered_name)
@@ -552,6 +574,34 @@ defmodule Logger.TranslatorTest do
552574
assert_receive {:event, {:string, ["Process " | _]}, _process_metadata}
553575
end
554576

577+
test "translates :gen_statem crashes when format_status/2 does not return a tuple" do
578+
{:ok, pid} = :gen_statem.start(MyGenStatemFormatStatus, :ok, [])
579+
580+
assert capture_log(:debug, fn ->
581+
catch_exit(:gen_statem.call(pid, :error))
582+
end) =~ ~r"""
583+
\[error\] :gen_statem #PID<\d+\.\d+\.\d+> terminating
584+
\*\* \(RuntimeError\) oops
585+
.*
586+
Queue: .*
587+
Postponed: \[\]
588+
State: :ok
589+
Callback mode: .*, state_enter: false
590+
"""s
591+
592+
assert_receive {:event, {:string, [[":gen_statem " <> _ | _] | _]}, gen_statem_metadata}
593+
assert_receive {:event, {:string, ["Process " | _]}, process_metadata}
594+
595+
assert {%RuntimeError{message: "oops"}, [_ | _]} = gen_statem_metadata[:crash_reason]
596+
assert {%RuntimeError{message: "oops"}, [_ | _]} = process_metadata[:crash_reason]
597+
598+
refute Map.has_key?(gen_statem_metadata, :initial_call)
599+
assert process_metadata[:initial_call] == {MyGenStatemFormatStatus, :init, 1}
600+
601+
refute Map.has_key?(gen_statem_metadata, :registered_name)
602+
refute Map.has_key?(process_metadata, :registered_name)
603+
end
604+
555605
test "translates Task crashes" do
556606
{:ok, pid} = Task.start_link(__MODULE__, :task, [self()])
557607
parent = self()

0 commit comments

Comments
 (0)