@@ -220,10 +220,17 @@ terminate(_, _) ->
220220% %--------------------------------------------------------------------------
221221% % error handling / termination
222222
223- close (Error , State = # v1 {connection = # v1_connection {timeout = Timeout }}) ->
223+ close (Error , State0 = # v1 {connection = # v1_connection {timeout = Timeout }}) ->
224224 % % Client properties will be emitted in the connection_closed event by rabbit_reader.
225- ClientProperties = i (client_properties , State ),
225+ ClientProperties = i (client_properties , State0 ),
226226 put (client_properties , ClientProperties ),
227+
228+ % % "It is illegal to send any more frames (or bytes of any other kind)
229+ % % after sending a close frame." [2.7.9]
230+ % % Sessions might send frames via the writer proc.
231+ % % Therefore, let's first try to orderly shutdown our sessions.
232+ State = shutdown_sessions (State0 ),
233+
227234 Time = case Timeout > 0 andalso
228235 Timeout < ? CLOSING_TIMEOUT of
229236 true -> Timeout ;
@@ -233,6 +240,31 @@ close(Error, State = #v1{connection = #v1_connection{timeout = Timeout}}) ->
233240 ok = send_on_channel0 (State , # 'v1_0.close' {error = Error }, amqp10_framing ),
234241 State # v1 {connection_state = closed }.
235242
243+ shutdown_sessions (# v1 {tracked_channels = Channels } = State ) ->
244+ maps :foreach (fun (_ChannelNum , Pid ) ->
245+ gen_server :cast (Pid , shutdown )
246+ end , Channels ),
247+ TimerRef = erlang :send_after (? SHUTDOWN_SESSIONS_TIMEOUT ,
248+ self (),
249+ shutdown_sessions_timeout ),
250+ wait_for_shutdown_sessions (TimerRef , State ).
251+
252+ wait_for_shutdown_sessions (TimerRef , # v1 {tracked_channels = Channels } = State )
253+ when map_size (Channels ) =:= 0 ->
254+ ok = erlang :cancel_timer (TimerRef , [{async , false },
255+ {info , false }]),
256+ State ;
257+ wait_for_shutdown_sessions (TimerRef , # v1 {tracked_channels = Channels } = State0 ) ->
258+ receive
259+ {{'DOWN' , ChannelNum }, _MRef , process , SessionPid , _Reason } ->
260+ State = untrack_channel (ChannelNum , SessionPid , State0 ),
261+ wait_for_shutdown_sessions (TimerRef , State );
262+ shutdown_sessions_timeout ->
263+ ? LOG_INFO (" sessions running ~b ms after requested to be shut down: ~p " ,
264+ [? SHUTDOWN_SESSIONS_TIMEOUT , maps :values (Channels )]),
265+ State0
266+ end .
267+
236268handle_session_exit (ChannelNum , SessionPid , Reason , State0 ) ->
237269 State = untrack_channel (ChannelNum , SessionPid , State0 ),
238270 S = case terminated_normally (Reason ) of
@@ -760,6 +792,7 @@ send_to_new_session(
760792 connection = # v1_connection {outgoing_max_frame_size = MaxFrame ,
761793 vhost = Vhost ,
762794 user = User ,
795+ container_id = ContainerId ,
763796 name = ConnName },
764797 writer = WriterPid } = State ) ->
765798 % % Subtract fixed frame header size.
@@ -772,6 +805,7 @@ send_to_new_session(
772805 OutgoingMaxFrameSize ,
773806 User ,
774807 Vhost ,
808+ ContainerId ,
775809 ConnName ,
776810 BeginFrame ],
777811 case rabbit_amqp_session_sup :start_session (SessionSup , ChildArgs ) of
0 commit comments