Skip to content
This repository was archived by the owner on Nov 18, 2020. It is now read-only.

Commit 33d9555

Browse files
author
Matthew Sackman
committed
Merging bug22994 into default
2 parents 369e2e2 + ea81f1b commit 33d9555

File tree

4 files changed

+85
-76
lines changed

4 files changed

+85
-76
lines changed

src/amqp_channel_util.erl

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -59,22 +59,12 @@ start_channel_infrastructure(network, ChannelNumber, {Sock, MainReader}) ->
5959
FramingPid = rabbit_framing_channel:start_link(fun(X) -> X end, [self()]),
6060
WriterPid = rabbit_writer:start_link(Sock, ChannelNumber, ?FRAME_MIN_SIZE),
6161
case MainReader of
62-
none ->
63-
ok;
64-
_ ->
65-
MainReader ! {register_framing_channel, ChannelNumber, FramingPid,
66-
self()},
67-
MonitorRef = erlang:monitor(process, MainReader),
68-
receive
69-
registered_framing_channel ->
70-
erlang:demonitor(MonitorRef), ok;
71-
{'DOWN', MonitorRef, process, MainReader, _Info} ->
72-
erlang:error(main_reader_died_while_registering_framing)
73-
end
62+
none -> ok;
63+
_ -> amqp_main_reader:register_framing_channel(
64+
MainReader, ChannelNumber, FramingPid)
7465
end,
7566
{FramingPid, WriterPid};
76-
start_channel_infrastructure(
77-
direct, ChannelNumber, {User, VHost, Collector}) ->
67+
start_channel_infrastructure(direct, ChannelNumber, {User, VHost, Collector}) ->
7868
Peer = rabbit_channel:start_link(ChannelNumber, self(), self(), User, VHost,
7969
Collector),
8070
{Peer, Peer}.

src/amqp_main_reader.erl

Lines changed: 78 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -27,47 +27,76 @@
2727

2828
-include("amqp_client.hrl").
2929

30-
-export([start/2]).
30+
-behaviour(gen_server).
31+
32+
-export([start_link/2, register_framing_channel/3, start_heartbeat/2]).
33+
-export([init/1, terminate/2, code_change/3, handle_call/3, handle_cast/2,
34+
handle_info/2]).
3135

3236
-record(mr_state, {sock,
3337
message = none, %% none | {Type, Channel, Length}
3438
framing_channels = amqp_channel_util:new_channel_dict()}).
3539

36-
start(Sock, Framing0Pid) ->
37-
spawn_link(
38-
fun() ->
39-
State0 = #mr_state{sock = Sock},
40-
State1 = register_framing_channel(0, Framing0Pid, none, State0),
41-
{ok, _Ref} = rabbit_net:async_recv(Sock, 7, infinity),
42-
main_loop(State1)
43-
end).
44-
45-
main_loop(State = #mr_state{sock = Sock}) ->
46-
receive
47-
{inet_async, Sock, _, _} = InetAsync ->
48-
main_loop(handle_inet_async(InetAsync, State));
49-
{heartbeat, Heartbeat} ->
50-
rabbit_heartbeat:start_heartbeat(Sock, Heartbeat),
51-
main_loop(State);
52-
{register_framing_channel, Number, Pid, Caller} ->
53-
main_loop(register_framing_channel(Number, Pid, Caller, State));
54-
timeout ->
55-
?LOG_WARN("Main reader (~p) received timeout from heartbeat, "
56-
"exiting~n", [self()]),
57-
exit(connection_timeout);
58-
socket_closing_timeout ->
59-
?LOG_WARN("Main reader (~p) received socket_closing_timeout, "
60-
"exiting~n", [self()]),
61-
exit(socket_closing_timeout);
62-
close ->
63-
close(State);
64-
{'DOWN', _MonitorRef, process, _Pid, _Info} = Down ->
65-
main_loop(handle_down(Down, State));
66-
Other ->
67-
?LOG_WARN("Main reader (~p) closing: unexpected message ~p",
68-
[self(), Other]),
69-
exit({unexpected_message, Other})
70-
end.
40+
%%---------------------------------------------------------------------------
41+
%% Interface
42+
%%---------------------------------------------------------------------------
43+
44+
start_link(Sock, Framing0Pid) ->
45+
gen_server:start_link(?MODULE, [Sock, Framing0Pid], []).
46+
47+
register_framing_channel(MainReaderPid, Number, FramingPid) ->
48+
gen_server:call(MainReaderPid,
49+
{register_framing_channel, Number, FramingPid}, infinity).
50+
51+
start_heartbeat(MainReaderPid, Heartbeat) ->
52+
gen_server:cast(MainReaderPid, {heartbeat, Heartbeat}).
53+
54+
%%---------------------------------------------------------------------------
55+
%% gen_server callbacks
56+
%%---------------------------------------------------------------------------
57+
58+
init([Sock, Framing0Pid]) ->
59+
State0 = #mr_state{sock = Sock},
60+
State1 = internal_register_framing_channel(0, Framing0Pid, State0),
61+
{ok, _Ref} = rabbit_net:async_recv(Sock, 7, infinity),
62+
{ok, State1}.
63+
64+
terminate(Reason, #mr_state{sock = Sock}) ->
65+
Nice = case Reason of
66+
normal -> true;
67+
shutdown -> true;
68+
{shutdown, _} -> true;
69+
_ -> false
70+
end,
71+
ok = case Nice of
72+
true -> rabbit_net:close(Sock);
73+
false -> ok
74+
end.
75+
76+
code_change(_OldVsn, State, _Extra) ->
77+
State.
78+
79+
handle_call({register_framing_channel, Number, Pid}, _From, State) ->
80+
{reply, ok, internal_register_framing_channel(Number, Pid, State)}.
81+
82+
handle_cast({heartbeat, Heartbeat}, State = #mr_state{sock = Sock}) ->
83+
rabbit_heartbeat:start_heartbeat(Sock, Heartbeat),
84+
{noreply, State}.
85+
86+
handle_info({inet_async, _, _, _} = InetAsync, State) ->
87+
handle_inet_async(InetAsync, State);
88+
handle_info({'DOWN', _, _, _, _} = Down, State) ->
89+
handle_down(Down, State);
90+
handle_info(timeout, State) ->
91+
{stop, connection_timeout, State};
92+
handle_info(socket_closing_timeout, State) ->
93+
{stop, socket_closing_timeout, State};
94+
handle_info(close, State) ->
95+
{stop, normal, State}.
96+
97+
%%---------------------------------------------------------------------------
98+
%% Internal plumbing
99+
%%---------------------------------------------------------------------------
71100

72101
handle_inet_async({inet_async, Sock, _, Msg},
73102
State = #mr_state{sock = Sock,
@@ -79,19 +108,18 @@ handle_inet_async({inet_async, Sock, _, Msg},
79108
case Msg of
80109
{ok, <<Payload:Length/binary, ?FRAME_END>>} ->
81110
case handle_frame(Type, Channel, Payload, State) of
82-
closed_ok -> close(State);
111+
closed_ok -> {stop, normal, State};
83112
_ -> {ok, _Ref} =
84113
rabbit_net:async_recv(Sock, 7, infinity),
85-
State#mr_state{message = none}
114+
{noreply, State#mr_state{message = none}}
86115
end;
87116
{ok, <<NewType:8, NewChannel:16, NewLength:32>>} ->
88117
{ok, _Ref} = rabbit_net:async_recv(Sock, NewLength + 1, infinity),
89-
State#mr_state{message = {NewType, NewChannel, NewLength}};
118+
{noreply, State#mr_state{message={NewType, NewChannel, NewLength}}};
90119
{error, closed} ->
91-
exit(socket_closed);
120+
{stop, socket_closed, State};
92121
{error, Reason} ->
93-
?LOG_WARN("Socket error: ~p~n", [Reason]),
94-
exit({socket_error, Reason})
122+
{stop, {socket_error, Reason}, State}
95123
end.
96124

97125
handle_frame(Type, Channel, Payload, State) ->
@@ -122,29 +150,20 @@ pass_frame(Channel, Frame, #mr_state{framing_channels = Channels}) ->
122150
rabbit_framing_channel:process(FramingPid, Frame)
123151
end.
124152

125-
register_framing_channel(Number, Pid, Caller,
126-
State = #mr_state{framing_channels = Channels}) ->
127-
NewChannels = amqp_channel_util:register_channel(Number, Pid, Channels),
128-
erlang:monitor(process, Pid),
129-
case Caller of
130-
none -> ok;
131-
_ -> Caller ! registered_framing_channel
132-
end,
133-
State#mr_state{framing_channels = NewChannels}.
134-
135153
handle_down({'DOWN', _MonitorRef, process, Pid, Info},
136154
State = #mr_state{framing_channels = Channels}) ->
137155
case amqp_channel_util:is_channel_pid_registered(Pid, Channels) of
138156
true ->
139157
NewChannels =
140158
amqp_channel_util:unregister_channel_pid(Pid, Channels),
141-
State#mr_state{framing_channels = NewChannels};
159+
{noreply, State#mr_state{framing_channels = NewChannels}};
142160
false ->
143-
?LOG_WARN("Reader received unexpected DOWN signal from (~p)."
144-
"Info: ~p~n", [Pid, Info]),
145-
exit({unexpected_down, Pid, Info})
161+
{stop, {unexpected_down, Pid, Info}, State}
146162
end.
147163

148-
close(#mr_state{sock = Sock}) ->
149-
rabbit_net:close(Sock),
150-
exit(normal).
164+
internal_register_framing_channel(
165+
Number, Pid, State = #mr_state{framing_channels = Channels}) ->
166+
NewChannels = amqp_channel_util:register_channel(Number, Pid, Channels),
167+
erlang:monitor(process, Pid),
168+
State#mr_state{framing_channels = NewChannels}.
169+

src/amqp_network_connection.erl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,12 +385,12 @@ do_handshake(State0 = #nc_state{sock = Sock}) ->
385385
ok = rabbit_net:send(Sock, ?PROTOCOL_HEADER),
386386
{Framing0Pid, Writer0Pid} =
387387
amqp_channel_util:start_channel_infrastructure(network, 0, {Sock, none}),
388-
MainReaderPid = amqp_main_reader:start(Sock, Framing0Pid),
388+
{ok, MainReaderPid} = amqp_main_reader:start_link(Sock, Framing0Pid),
389389
State1 = State0#nc_state{channel0_framing_pid = Framing0Pid,
390390
channel0_writer_pid = Writer0Pid,
391391
main_reader_pid = MainReaderPid},
392392
State2 = network_handshake(State1),
393-
MainReaderPid ! {heartbeat, State2#nc_state.heartbeat},
393+
amqp_main_reader:start_heartbeat(MainReaderPid, State2#nc_state.heartbeat),
394394
State2.
395395

396396
network_handshake(State = #nc_state{channel0_writer_pid = Writer0,

test/amqp_dbg.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ all_args() ->
8888
ncl_args() ++ dcl_args() ++ cl_args() ++ m_args().
8989

9090
ncl_args() ->
91-
[{amqp_main_reader, start, return_ms()},
91+
[{amqp_main_reader, start_link, return_ms()},
9292
{amqp_network_connection, set_closing_state, []},
9393
{amqp_network_connection, all_channels_closed_event, []},
9494
{amqp_network_connection, handshake, []},

0 commit comments

Comments
 (0)