Timeouted gen_server:call

Dmitry Belyaev rumata-estor@REDACTED
Wed May 12 16:48:25 CEST 2010


I have a gen_server and many clients. Clients send request to the server 
with gen_server:call(Server, Msg, Timeout) and when timeout occurs they 
ask server to abort appropriate reply. But server may reply right before 
it receives abort message and I may get trash in client's mailbox.

I'm not sure that client can throw away this trash itself. So it is 
possible for client to fill his message queue with lots of such messages.

I may not let client crash. Neither I don't want to spawn new process 
for every such request.

Looking through gen module I found that wait_resp*/3 could tell me Mref 
with exit({timeout, Mref}). Then I could use gen:call() and catch that 
Mref. But it currently doesn't offer such information.


So, I'd like to know how more experienced programmers workaround this 
problem.


Code like this:

-export([do_call/4, handle_call/3, handle_info/2]).

do_call(Server, MsgId, Msg, Timeout) ->
    try gen_server:call(Server, {process, MsgId, Msg}, Timeout) of
       Response ->
          Response
    catch
       exit:{timeout, Reason} ->
          %% this is a place when server can reply us
          Server ! {abort, MsgId},
          %% here I'd like to cleanup message queue but I don't know Mref
          error
    end.


handle_call({process, MsgId, Msg}, From, State) ->
    start_processing(MsgId, Msg),
    {noreply, State#state{ids=[{MsgId, From} | State#state.ids]}}.


handle_info({ready, MsgId, Response}, State) ->
    case get_from(MsgId, State) of
       undefined ->
          {noreply, State};
        {From, NewState} ->
            gen_server:reply(From, Response),
          {noreply, NewState}
    end;

handle_info({abort, MsgId}, State) ->
    case get_from(MsgId, State) of
       undefined ->
            {noreply, State};
       {_, NewState} ->
          {noreply, NewState}
    end.



More information about the erlang-questions mailing list