diff options
Diffstat (limited to 'p11p-daemon')
-rw-r--r-- | p11p-daemon/src/p11p_remote.erl | 21 | ||||
-rw-r--r-- | p11p-daemon/src/p11p_remote_manager.erl | 37 |
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}. |