aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuan Facorro <[email protected]>2015-06-21 20:09:10 -0300
committerLoïc Hoguin <[email protected]>2017-04-30 17:42:27 +0200
commitfb4bd38ffd2c330cbd677d958477aa909210a0b3 (patch)
tree1bef7a85e5f4204b144e96d4682a5c541bc3bdaa
parent7a213b6a95357c5304e9d9a2a52930882bf8305e (diff)
downloadgun-fb4bd38ffd2c330cbd677d958477aa909210a0b3.tar.gz
gun-fb4bd38ffd2c330cbd677d958477aa909210a0b3.tar.bz2
gun-fb4bd38ffd2c330cbd677d958477aa909210a0b3.zip
Monitor owner and terminate when it dies
-rw-r--r--src/gun.erl11
-rw-r--r--test/gun_SUITE.erl22
2 files changed, 31 insertions, 2 deletions
diff --git a/src/gun.erl b/src/gun.erl
index 4304299..16397c9 100644
--- a/src/gun.erl
+++ b/src/gun.erl
@@ -99,6 +99,7 @@
-record(state, {
parent :: pid(),
owner :: pid(),
+ owner_ref :: reference(),
host :: inet:hostname(),
port :: inet:port_number(),
opts :: opts(),
@@ -487,7 +488,9 @@ init(Parent, Owner, Host, Port, Opts) ->
tcp -> ranch_tcp;
ssl -> ranch_ssl
end,
- connect(#state{parent=Parent, owner=Owner, host=Host, port=Port, opts=Opts, transport=Transport}, Retry).
+ OwnerRef = monitor(process, Owner),
+ connect(#state{parent=Parent, owner=Owner, owner_ref=OwnerRef,
+ host=Host, port=Port, opts=Opts, transport=Transport}, Retry).
default_transport(443) -> ssl;
default_transport(_) -> tcp.
@@ -576,7 +579,7 @@ before_loop(State=#state{opts=Opts, protocol=Protocol}) ->
KeepaliveRef = erlang:send_after(Keepalive, self(), keepalive),
loop(State#state{keepalive_ref=KeepaliveRef}).
-loop(State=#state{parent=Parent, owner=Owner, host=Host, port=Port, opts=Opts,
+loop(State=#state{parent=Parent, owner=Owner, owner_ref=OwnerRef, host=Host, port=Port, opts=Opts,
socket=Socket, transport=Transport, protocol=Protocol, protocol_state=ProtoState}) ->
{OK, Closed, Error} = Transport:messages(),
Transport:setopts(Socket, [{active, once}]),
@@ -636,6 +639,10 @@ loop(State=#state{parent=Parent, owner=Owner, host=Host, port=Port, opts=Opts,
{shutdown, Owner} ->
%% @todo Protocol:shutdown?
ok;
+ {'DOWN', OwnerRef, process, Owner, Reason} ->
+ Protocol:close(ProtoState),
+ Transport:close(Socket),
+ error({owner_gone, Reason});
{system, From, Request} ->
sys:handle_system_msg(Request, From, Parent, ?MODULE, [],
{loop, State});
diff --git a/test/gun_SUITE.erl b/test/gun_SUITE.erl
index c62c600..64b8885 100644
--- a/test/gun_SUITE.erl
+++ b/test/gun_SUITE.erl
@@ -42,6 +42,28 @@ connect_timeout_infinity(_) ->
error(timeout)
end.
+detect_owner_gone(_) ->
+ Self = self(),
+ spawn(fun() ->
+ {ok, ConnPid} = gun:open("google.com", 80),
+ Self ! {conn, ConnPid},
+ gun:await_up(ConnPid)
+ end),
+ Pid = receive
+ {conn, C} ->
+ C
+ after 1000 ->
+ error(timeout)
+ end,
+ Ref = monitor(process, Pid),
+ receive
+ {'DOWN', Ref, process, Pid, {owner_gone, _}} ->
+ ok
+ after 1000 ->
+ true = erlang:is_process_alive(Pid),
+ error(timeout)
+ end.
+
gone_reason(_) ->
doc("The last connection failure must be propagated."),
{ok, Pid} = gun:open("localhost", 12345, #{retry => 0}),