Alex P.
Alex P.

Reputation: 551

Timeout error in recursive call of handle_call/3 of behaviour(gen_server), Erlang/OTP

I'm trying to make a recursive call to handle_call/3 before replying. But it seems to not be possible, because a timeout exit exception is thrown. Below you can see the code and the error.

The code:

-module(test).
-behavior(gen_server).

%% API
-export([start_link/0,init/1,handle_info/2,first_call/1,second_call/1, handle_call/3, terminate/2]).

-record(state, {whatever}).

start_link() ->
  gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).

init(_Args) ->
  {ok, #state{}}.

handle_info(Data, State) ->
  {noreply, State}.

% synchronous messages
handle_call(_Request, _From, State) ->
  case _Request of
    first_call ->
      {reply, data1, State};
    second_call ->
      {reply, {data2, first_call(self())}, State}
  end.

first_call(Pid) ->
  gen_server:call(Pid, first_call).

second_call(Pid) ->
  gen_server:call(Pid, second_call).

terminate(_Reason, _State) ->
  ok.

The error:

2> {_, PID} = test:start_link().
{ok,<0.64.0>}
3> test:second_call(PID).
** exception exit: {timeout,{gen_server,call,[<0.64.0>,second_call]}}
     in function  gen_server:call/2 (gen_server.erl, line 204) 

A possible reason for this behaviour is that gen_server is not able to handle recursive calls until the first one is done (creating a deadlock). Is this the right reason, and if yes why? Thanks.

Upvotes: 1

Views: 501

Answers (1)

legoscia
legoscia

Reputation: 41648

Yes, that is the reason. The gen_server is a single process, and while handle_call is executing it doesn't pick up any messages nor respond to any gen_server:call. Therefore first_call(self()) times out.

Upvotes: 6

Related Questions