Use link/unlink for hidden nodes
link/unlink is supported by JInterface which presents as a hidden
node, this enhancement to ioq allows us to ditch scalang among other
effects.
diff --git a/src/ioq_server.erl b/src/ioq_server.erl
index c9fd79b..9b12986 100644
--- a/src/ioq_server.erl
+++ b/src/ioq_server.erl
@@ -94,6 +94,7 @@
histos = ets:new(ioq_histos, [named_table, ordered_set])
},
erlang:send_after(get_interval(), self(), dump_table),
+ process_flag(trap_exit, true),
{ok, update_config(State)}.
handle_call({set_priority, Pri}, _From, State) ->
@@ -146,7 +147,7 @@
case lists:keytake(Ref, #request.ref, Reqs) of
{value, #request{from=From} = Req, Reqs2} ->
TResponse = erlang:monotonic_time(),
- erlang:demonitor(Ref, [flush]),
+ demonitor_(Ref, Req#request.fd),
reply_to_all(From, Reply),
update_histograms(ioq_histos, Req, TResponse),
{noreply, State#state{reqs = Reqs2}, 0};
@@ -163,6 +164,12 @@
{noreply, State, 0}
end;
+handle_info({'EXIT', Pid, Reason}, #state{reqs = Reqs} = State) ->
+ {L1, L2} = lists:splitwith(fun(R) -> Pid == R#request.fd end, Reqs),
+ lists:foreach(
+ fun(R) -> reply_to_all(R#request.from, {'EXIT', Reason}) end, L1),
+ {noreply, State#state{reqs = L2}, 0};
+
handle_info(dump_table, State) ->
erlang:send_after(get_interval(), self(), dump_table),
{noreply, dump_table(State), 0};
@@ -414,7 +421,7 @@
#state{reqs = Reqs, counters = Counters} = State,
% make the request
- Ref = erlang:monitor(process, Fd),
+ Ref = monitor_(Fd),
Fd ! {'$gen_call', {self(), Ref}, Call},
% record some stats
@@ -598,6 +605,50 @@
rw(_) ->
unknown.
+
+monitor_(Pid) when is_pid(Pid) ->
+ case is_hidden(Pid) of
+ true ->
+ link(Pid),
+ make_ref();
+ false ->
+ erlang:monitor(process, Pid)
+ end;
+
+monitor_({Name, Node}) when is_atom(Name), is_atom(Node) ->
+ case is_hidden(Node) of
+ true ->
+ make_ref();
+ false ->
+ erlang:monitor(process, {Name, Node})
+ end.
+
+
+demonitor_(Ref, Pid) when is_reference(Ref), is_pid(Pid) ->
+ case is_hidden(Pid) of
+ true ->
+ unlink(Pid);
+ false ->
+ erlang:demonitor(Ref, [flush])
+ end;
+
+demonitor_(Ref, {Name, Node})
+ when is_reference(Ref), is_atom(Name), is_atom(Node) ->
+ case is_hidden(Node) of
+ true ->
+ ok;
+ false ->
+ erlang:demonitor(Ref, [flush])
+ end.
+
+
+is_hidden(Pid) when is_pid(Pid) ->
+ is_hidden(node(Pid));
+
+is_hidden(Node) when is_atom(Node) ->
+ lists:member(Node, nodes(hidden)).
+
+
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").