%% ProtocolFactory :: fun() -> thrift_protocol()
start(ProtocolFactory, Service, ClientOpts)
when is_function(ProtocolFactory), is_atom(Service) ->
- Starter =
+ {Starter, Opts} =
case lists:keysearch(monitor, 1, ClientOpts) of
{value, {monitor, link}} ->
- start_link;
+ {start_link, []};
+ {value, {monitor, tether}} ->
+ {start, [{tether, self()}]};
_ ->
- start
+ {start, []}
end,
Connect =
end,
- Started = gen_server:Starter(?MODULE, [Service], []),
+ Started = gen_server:Starter(?MODULE, [Service, Opts], []),
if
Connect ->
%% {stop, Reason}
%% Description: Initiates the server
%%--------------------------------------------------------------------
-init([Service]) ->
+init([Service, Opts]) ->
+ case lists:keysearch(tether, 1, Opts) of
+ {value, {tether, Pid}} ->
+ erlang:monitor(process, Pid);
+ _Else ->
+ ok
+ end,
{ok, #state{service = Service}}.
%%--------------------------------------------------------------------
%% {stop, Reason, State}
%% Description: Handling all non call/cast messages
%%--------------------------------------------------------------------
+handle_info({'DOWN', MonitorRef, process, Pid, _Info}, State)
+ when is_reference(MonitorRef), is_pid(Pid) ->
+ %% We don't actually verify the correctness of the DOWN message.
+ {stop, parent_died, State};
+
handle_info(_Info, State) ->
{noreply, State}.
io:format("PASS. Linked owner is dead.~n")
end,
- check_extras(2),
+ Pid3 = erlang:spawn(?MODULE, test_tethered, []),
+ receive after 200 -> ok end, % Wait for completion.
+ case is_up(Pid3) of
+ true ->
+ io:format("PASS. Tethered owner still alive.~n");
+ false ->
+ io:format("FAIL. Tethered owner is dead.~n")
+ end,
+
+ check_extras(3),
erlang:halt().
{linked, true} ->
io:format("FAIL. Linked client still alive.~n");
{linked, false} ->
- io:format("PASS. Linked client dead.~n")
+ io:format("PASS. Linked client dead.~n");
+ {tethered, true} ->
+ io:format("FAIL. Tethered client still alive.~n");
+ {tethered, false} ->
+ io:format("PASS. Tethered client dead.~n")
end,
check_extras(N-1)
after
%% Exit abnormally to kill our linked extra client.
%% But we should never get here.
exit(die).
+
+test_tethered() ->
+ {ok, Client1} = make_thrift_client([{connect, false}, {monitor, tether}]),
+ tester ! {client, tethered, Client1},
+ {ok, Client2} = make_thrift_client([{connect, false}, {monitor, tether}]),
+ io:format("PASS. Tethered clients created.~n"),
+ try
+ gen_server:call(Client2, {connect, make_protocol_factory(2)}),
+ io:format("FAIL. Tethered client connected.~n", [])
+ catch
+ Kind:Info ->
+ io:format("PASS. Caught tethered error. ~p:~p~n", [Kind, Info])
+ end,
+ receive after 100 ->
+ io:format("PASS. Still alive after tethered death.~n"),
+ % Hang around a little longer so our parent can verify.
+ receive after 200 -> ok end
+ end,
+ %% Exit abnormally to kill our tethered extra client.
+ exit(die).