Question

I have an erlang service that trigged by erl_call. erl_call will make a long call like "gen_server:call(?SERVER, do, infinity)" to wait the result. If erlang service down, erl_call will return. But if erl_call be interrupted (use CTRL-C), the erlang service do not receive any message.

I check with appmon and pman. The process that erl_call started not die after erl_call disconnected. So link/monitor to that process is not work. How do I detect erl_call already disconnected?

Was it helpful?

Solution

In your handle_call function there is a second. argument From :: {pid(), tag()}

You can call monitor(process, FromPid) in handle_call before processing the request so you'll receive DOWN message when your erl_call node disconnects. But note that you won't be able to process DOWN message before current handle_call completes unless you spawn a separate process or use delayed reply with gen_server:reply().

For example: here's our handle_call clause:

handle_call(test, {From, _}=X, State) ->
    erlang:monitor(process, From),

    spawn(fun() ->
       timer:sleep(10000),
       io:format("### DONE~n", []),
       gen_server:reply(X, ok) end),

    {noreply, State}.

Next we catch DOWN:

handle_info(Info, State) ->
    io:format("### Process died ~p~n", [Info]),
    {noreply, State}.

Next I spawn erl_call from command line: erl_call -c 123 -n test -a 'gen_server call [a, test, infinity]'

and hit Ctrl-C

in gen_server console after 10 sec I see:

### DONE            
### Process died {'DOWN',#Ref<0.0.0.41>,process,<0.44.0>,normal}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top