Search code examples
erlangcallerl

How to detect erl_call disconnect


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?


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}