Monitor owner process and handle normal termination
This commit is contained in:
parent
0436704327
commit
7347906f29
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
-record(enoise, { pid }).
|
-record(enoise, { pid }).
|
||||||
|
|
||||||
-record(state, {rx, tx, owner, tcp_sock, active, msgbuf = [], rawbuf = <<>>}).
|
-record(state, {rx, tx, owner, owner_ref, tcp_sock, active, msgbuf = [], rawbuf = <<>>}).
|
||||||
|
|
||||||
%% -- API --------------------------------------------------------------------
|
%% -- API --------------------------------------------------------------------
|
||||||
start_link(TcpSock, Rx, Tx, Owner, {Active0, Buf}) ->
|
start_link(TcpSock, Rx, Tx, Owner, {Active0, Buf}) ->
|
||||||
@ -33,8 +33,10 @@ start_link(TcpSock, Rx, Tx, Owner, {Active0, Buf}) ->
|
|||||||
true -> true;
|
true -> true;
|
||||||
once -> {once, false}
|
once -> {once, false}
|
||||||
end,
|
end,
|
||||||
State = #state{ rx = Rx, tx = Tx, owner = Owner,
|
OwnerRef = erlang:monitor(process, Owner),
|
||||||
|
State = #state{ rx = Rx, tx = Tx, owner = Owner, owner_ref = OwnerRef,
|
||||||
tcp_sock = TcpSock, active = Active },
|
tcp_sock = TcpSock, active = Active },
|
||||||
|
|
||||||
case gen_server:start_link(?MODULE, [State], []) of
|
case gen_server:start_link(?MODULE, [State], []) of
|
||||||
{ok, Pid} ->
|
{ok, Pid} ->
|
||||||
case gen_tcp:controlling_process(TcpSock, Pid) of
|
case gen_tcp:controlling_process(TcpSock, Pid) of
|
||||||
@ -99,12 +101,19 @@ handle_info({tcp, TS, Data}, S = #state{ tcp_sock = TS, owner = O }) ->
|
|||||||
handle_info({tcp_closed, TS}, S = #state{ tcp_sock = TS, owner = O }) ->
|
handle_info({tcp_closed, TS}, S = #state{ tcp_sock = TS, owner = O }) ->
|
||||||
O ! {tcp_closed, TS},
|
O ! {tcp_closed, TS},
|
||||||
{noreply, S#state{ tcp_sock = closed }};
|
{noreply, S#state{ tcp_sock = closed }};
|
||||||
handle_info(Msg, S) ->
|
handle_info({'DOWN', OwnerRef, process, _, normal},
|
||||||
io:format("Unexpected info: ~p\n", [Msg]),
|
S = #state { tcp_sock = TS, owner_ref = OwnerRef }) ->
|
||||||
|
gen_tcp:close(TS),
|
||||||
|
{stop, normal, S#state{ tcp_sock = closed, owner_ref = undefined }};
|
||||||
|
handle_info({'DOWN', _, _, _, _}, S) ->
|
||||||
|
%% Ignore non-normal monitor messages - we are linked.
|
||||||
|
{noreply, S};
|
||||||
|
handle_info(_Msg, S) ->
|
||||||
{noreply, S}.
|
{noreply, S}.
|
||||||
|
|
||||||
terminate(_Reason, #state{ tcp_sock = TcpSock }) ->
|
terminate(_Reason, #state{ tcp_sock = TcpSock, owner_ref = ORef }) ->
|
||||||
[ gen_tcp:close(TcpSock) || TcpSock /= closed ],
|
[ gen_tcp:close(TcpSock) || TcpSock /= closed ],
|
||||||
|
[ erlang:demonitor(ORef, [flush]) || ORef /= undefined ],
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
code_change(_OldVsn, State, _Extra) ->
|
code_change(_OldVsn, State, _Extra) ->
|
||||||
@ -112,11 +121,10 @@ code_change(_OldVsn, State, _Extra) ->
|
|||||||
|
|
||||||
|
|
||||||
%% -- Local functions --------------------------------------------------------
|
%% -- Local functions --------------------------------------------------------
|
||||||
handle_control_change(S = #state{ owner = Pid, tcp_sock = TcpSock }, Pid, NewPid) ->
|
handle_control_change(S = #state{ owner = Pid, owner_ref = OldRef }, Pid, NewPid) ->
|
||||||
case gen_tcp:controlling_process(TcpSock, NewPid) of
|
NewRef = erlang:monitor(process, NewPid),
|
||||||
ok -> {ok, S#state{ owner = NewPid }};
|
erlang:demonitor(OldRef, [flush]),
|
||||||
Err = {error, _} -> {Err, S}
|
{ok, S#state{ owner = NewPid, owner_ref = NewRef }};
|
||||||
end;
|
|
||||||
handle_control_change(S, _OldPid, _NewPid) ->
|
handle_control_change(S, _OldPid, _NewPid) ->
|
||||||
{{error, not_owner}, S}.
|
{{error, not_owner}, S}.
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user