Skip to content

Commit ca95915

Browse files
Merge pull request #16743 from rabbitmq/mergify/bp/v4.3.x/pr-16740
Handle unexpected failures during channel termination cleanup (backport #16740)
2 parents dcd66da + 3106e69 commit ca95915

2 files changed

Lines changed: 68 additions & 21 deletions

File tree

deps/rabbit/src/rabbit_channel.erl

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -713,26 +713,32 @@ terminate(_Reason,
713713
State = #ch{cfg = #conf{user = #user{username = Username}},
714714
consumer_mapping = CM,
715715
queue_states = QueueCtxs}) ->
716-
rabbit_queue_type:close(QueueCtxs),
717-
{_Res, _State1} = notify_queues(State),
718-
pg_local:leave(rabbit_channels, self()),
719-
rabbit_event:if_enabled(State, #ch.stats_timer,
720-
fun() -> emit_stats(State) end),
721-
[delete_stats(Tag) || {Tag, _} <- get()],
722-
maybe_decrease_global_publishers(State),
723-
maps:foreach(
724-
fun (_, _) ->
725-
rabbit_global_counters:consumer_deleted(amqp091)
726-
end, CM),
727-
rabbit_core_metrics:channel_closed(self()),
728-
rabbit_event:notify(channel_closed, [{pid, self()},
729-
{user_who_performed_action, Username},
730-
{consumer_count, maps:size(CM)}]),
731-
case rabbit_confirms:size(State#ch.unconfirmed) of
732-
0 -> ok;
733-
NumConfirms ->
734-
?LOG_WARNING("Channel is stopping with ~b pending publisher confirms",
735-
[NumConfirms])
716+
try
717+
rabbit_queue_type:close(QueueCtxs),
718+
{_Res, _State1} = notify_queues(State),
719+
pg_local:leave(rabbit_channels, self()),
720+
rabbit_event:if_enabled(State, #ch.stats_timer,
721+
fun() -> emit_stats(State) end),
722+
[delete_stats(Tag) || {Tag, _} <- get()],
723+
maybe_decrease_global_publishers(State),
724+
maps:foreach(
725+
fun (_, _) ->
726+
rabbit_global_counters:consumer_deleted(amqp091)
727+
end, CM),
728+
rabbit_core_metrics:channel_closed(self()),
729+
rabbit_event:notify(channel_closed, [{pid, self()},
730+
{user_who_performed_action, Username},
731+
{consumer_count, maps:size(CM)}]),
732+
case rabbit_confirms:size(State#ch.unconfirmed) of
733+
0 -> ok;
734+
NumConfirms ->
735+
?LOG_WARNING("Channel is stopping with ~b pending publisher confirms",
736+
[NumConfirms])
737+
end
738+
catch
739+
_Class:Reason ->
740+
?LOG_WARNING("Channel ~tp termination cleanup failed with reason: ~tp",
741+
[self(), Reason])
736742
end.
737743

738744
code_change(_OldVsn, State, _Extra) ->

deps/rabbit/test/channel_SUITE.erl

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ all() ->
2222
groups() ->
2323
[
2424
{non_parallel_tests, [], [
25-
ready_for_close_with_dead_writer
25+
ready_for_close_with_dead_writer,
26+
terminate_safely_handles_cleanup_failures
2627
]}
2728
].
2829

@@ -94,6 +95,46 @@ ready_for_close_with_dead_writer1(_Config) ->
9495
end,
9596
passed.
9697

98+
terminate_safely_handles_cleanup_failures(Config) ->
99+
passed = rabbit_ct_broker_helpers:rpc(Config, 0,
100+
?MODULE, terminate_safely_handles_cleanup_failures1, [Config]).
101+
102+
terminate_safely_handles_cleanup_failures1(_Config) ->
103+
{Writer, Ch} = start_channel_and_writer(),
104+
MRef = erlang:monitor(process, Ch),
105+
106+
%% Make rabbit_queue_type:close/1 crash to simulate an unexpected
107+
%% failure during channel termination cleanup.
108+
ok = meck:new(rabbit_queue_type, [passthrough]),
109+
meck:expect(rabbit_queue_type, close,
110+
fun(_) -> error(fake_cleanup_failure) end),
111+
112+
rabbit_channel_common:do(Ch, #'channel.close'{reply_code = 200,
113+
reply_text = <<"OK">>,
114+
class_id = 0,
115+
method_id = 0}),
116+
receive
117+
{channel_closing, Ch} -> ok
118+
after ?TIMEOUT ->
119+
meck:unload(rabbit_queue_type),
120+
throw(failed_to_receive_channel_closing)
121+
end,
122+
123+
exit(Writer, kill),
124+
125+
rabbit_channel_common:ready_for_close(Ch),
126+
receive
127+
{'DOWN', MRef, process, Ch, normal} ->
128+
meck:unload(rabbit_queue_type),
129+
passed;
130+
{'DOWN', MRef, process, Ch, Reason} ->
131+
meck:unload(rabbit_queue_type),
132+
throw({channel_should_terminate_normally, Reason})
133+
after ?TIMEOUT ->
134+
meck:unload(rabbit_queue_type),
135+
throw(channel_did_not_terminate)
136+
end.
137+
97138
start_channel_and_writer() ->
98139
{Writer, _Limiter, Ch} = rabbit_ct_broker_helpers:test_channel(),
99140
ok = rabbit_channel_common:do(Ch, #'channel.open'{}),

0 commit comments

Comments
 (0)