summaryrefslogtreecommitdiff
path: root/p11p-daemon
diff options
context:
space:
mode:
Diffstat (limited to 'p11p-daemon')
-rw-r--r--p11p-daemon/src/p11p_remote.erl21
-rw-r--r--p11p-daemon/src/p11p_remote_manager.erl37
2 files changed, 35 insertions, 23 deletions
diff --git a/p11p-daemon/src/p11p_remote.erl b/p11p-daemon/src/p11p_remote.erl
index 84299c5..9047cad 100644
--- a/p11p-daemon/src/p11p_remote.erl
+++ b/p11p-daemon/src/p11p_remote.erl
@@ -14,7 +14,7 @@
%% API.
-export([start_link/3]).
--export([request/2, add_to_outbuf/2]).
+-export([request/2, add_to_outbuf/2, stop/2]).
-include("p11p_rpc.hrl").
@@ -48,11 +48,20 @@ request(Remote, Request) ->
add_to_outbuf(Remote, Data) ->
gen_server:call(Remote, {add_to_outbuf, Data}).
+%% Use stop/1 instead of gen_server:stop/1 if you're uncertain whether
+%% Pid is alive or not. An example of when that can happen is when the
+%% manager receiving a server_event about a lost client. If the server
+%% process terminated on request from a remote which has timed out on
+%% an rpc call, chances are that the remote has already terminated by
+%% the time the manager is to act on the lost client.
+stop(Pid, Reason) ->
+ gen_server:cast(Pid, {stop, Reason}).
+
%% Genserver callbacks.
init([TokName, ModPath]) ->
Port = open_port({spawn_executable, ?P11KITREMOTE_PATH},
[stream, exit_status, {args, [ModPath, "-v"]}]),
- lager:debug("~p: ~s: New port: ~p", [self(), ?P11KITREMOTE_PATH, Port]),
+ lager:debug("~p: ~s: new remote port: ~p", [self(), ?P11KITREMOTE_PATH, Port]),
{ok, #state{port = Port, token = TokName}}.
handle_call({add_to_outbuf, Data}, _From, State) ->
@@ -65,8 +74,10 @@ handle_call(Request, _From, State) ->
lager:debug("~p: Unhandled call: ~p~n", [self(), Request]),
{reply, unhandled, State}.
-handle_cast(Request, State) ->
- lager:debug("~p: Unhandled cast: ~p~n", [self(), Request]),
+handle_cast({stop, Reason}, State) ->
+ {stop, Reason, State};
+handle_cast(Cast, State) ->
+ lager:debug("~p: unhandled cast: ~p~n", [self(), Cast]),
{noreply, State}.
%% TODO: dedup code w/ p11p_server
@@ -78,7 +89,7 @@ handle_info({Port, {data, Data}}, #state{msg = Msg} = State) when Port == State#
{noreply, handle_remote_data(State, Msg, Data)};
handle_info({timeout, Timer, Port}, #state{token = TokName, replyto = Server} = State) when Port == State#state.port, Timer == State#state.timer ->
lager:info("~p: rpc request timed out, exiting", [self()]),
- ok = p11p_remote_manager:server_event(timeout, [TokName, Server]),
+ p11p_remote_manager:server_event(timeout, [TokName, Server]),
NewState = State#state{timer = undefined},
{stop, normal, NewState};
handle_info(Info, State) ->
diff --git a/p11p-daemon/src/p11p_remote_manager.erl b/p11p-daemon/src/p11p_remote_manager.erl
index 0acec66..8ff8883 100644
--- a/p11p-daemon/src/p11p_remote_manager.erl
+++ b/p11p-daemon/src/p11p_remote_manager.erl
@@ -56,11 +56,11 @@ start_link() ->
-spec remote_for_token(string()) -> pid().
remote_for_token(TokName) ->
gen_server:call(?MODULE, {remote_for_token, TokName}).
-client_event(Change, Args) ->
- gen_server:call(?MODULE, {client_event, Change, Args}).
+client_event(Event, Args) ->
+ gen_server:cast(?MODULE, {client_event, Event, Args}).
-server_event(Change, Args) ->
- gen_server:call(?MODULE, {server_event, Change, Args}).
+server_event(Event, Args) ->
+ gen_server:cast(?MODULE, {server_event, Event, Args}).
%% Genserver callbacks.
init([]) ->
@@ -80,9 +80,13 @@ handle_call({remote_for_token, TokName}, _From, #state{tokens = Tokens} = State)
_ ->
{reply, Pid, State}
end;
-handle_call({server_event, timeout, [TokName, Server]}, _From, #state{tokens = Tokens} = State) ->
- lager:debug("~p: ~s: timed out", [self(), TokName]),
- gen_server:stop(Server), % Hang up p11 client.
+handle_call(Call, _From, State) ->
+ lager:debug("Unhandled call: ~p~n", [Call]),
+ {reply, unhandled, State}.
+
+handle_cast({server_event, timeout, [TokName, Server]}, #state{tokens = Tokens} = State) ->
+ lager:debug("~p: ~s: timed out, stopping ~p", [self(), TokName, Server]),
+ gen_server:stop(Server), % Hang up on p11 client.
%% TODO: do some code dedup with remote_for_token?
#{TokName := Token} = Tokens,
Remotes = Token#token.remotes,
@@ -91,10 +95,10 @@ handle_call({server_event, timeout, [TokName, Server]}, _From, #state{tokens = T
NewToken = Token#token{remotes = tl(Remotes) ++ [NewRemote]},
NewState = State#state{tokens = Tokens#{TokName := NewToken}},
lager:debug("~p: ~s: updated token: ~p", [self(), TokName, NewToken]),
- {reply, ok, NewState};
-handle_call({client_event, client_gone, [TokName, Pid]}, From, #state{tokens = Tokens} = State) ->
- lager:debug("~p: killing off remote ~p on request from ~p", [self(), Pid, From]),
- gen_server:stop(Pid),
+ {noreply, NewState};
+handle_cast({client_event, client_gone, [TokName, Pid]}, #state{tokens = Tokens} = State) ->
+ lager:debug("~p: asking remote ~p to stop", [self(), Pid]),
+ p11p_remote:stop(Pid, normal),
#{TokName := Token} = Tokens,
Remotes = Token#token.remotes,
NewRemotes = [case E#remote.pid of
@@ -103,18 +107,15 @@ handle_call({client_event, client_gone, [TokName, Pid]}, From, #state{tokens = T
end || E <- Remotes],
NewToken = Token#token{remotes = NewRemotes},
NewState = State#state{tokens = Tokens#{TokName := NewToken}},
- {reply, ok, NewState};
-handle_call(Call, _From, State) ->
- lager:debug("Unhandled call: ~p~n", [Call]),
- {reply, unhandled, State}.
-
+ {noreply, NewState};
handle_cast(Cast, State) ->
lager:debug("Unhandled cast: ~p~n", [Cast]),
{noreply, State}.
handle_info({Port, {exit_status, Status}}, State) ->
- lager:info("~p: process exited with ~p", [Port, Status]),
- {stop, child_exit, State};
+ %% FIXME: do we need to be trapping exits explicitly?
+ lager:info("~p: process ~p exited with ~p", [self(), Port, Status]),
+ {noreply, State};
handle_info(Info, State) ->
lager:debug("~p: Unhandled info: ~p~n", [self(), Info]),
{noreply, State}.