Reputation: 9360
I am using a gen_server behaviour and trying to understand how can handle_info/2
be triggered from a timeout
occurring in a handle_call
for example:
-module(server).
-export([init/1,handle_call/3,handle_info/2,terminate/2).
-export([start/0,stop/0]).
init(Data)->
{ok,33}.
start()->
gen_server:start_link(?MODULE,?MODULE,[]).
stop(Pid)->
gen_server:stop(Pid).
handle_call(Request,From,State)->
Return={reply,State,State,5000},
Return.
handle_info(Request,State)->
{stop,Reason,State}.
terminate(Reason,State)->
{ok,S}=file:file_open("D:/Erlang/Supervisor/err.txt",[read,write]),
io:format(S,"~s~n",[Reason]),
ok.
What i want to do:
I was expecting that if I launch the server and would not use gen_server:call/2
for 5
seconds (in my case) then handle_info
would be called, which would in turn issue the stop
thus calling terminate
.
I see it does not happen this way, in fact handle_info
is not called at all.
In examples such as this i see the timeout
is set in the return of init/1
.
What I can deduce is that it handle_info
gets triggered only if I initialize the server and issue nothing (nor cast
nor call
for N
seconds).If so why I can provide Timeout
in the return
of both handle_cast/2 and handle_call/3 ?
Update:
I was trying to get the following functionality:
call
is issued in X
seconds trigger handle_info/2
cast
is issued in Y
seconds trigger handle_info/2
I thought this timeouts can be set in the return
of handle_call
and handle_cast
:
{reply,Reply,State,X} //for call
{noreply,State,Y} //for cast
If not, when are those timeouts triggered since they are returns
?
Upvotes: 2
Views: 1089
Reputation: 91
i suggest you read source code:gen_server.erl
% gen_server.erl
% line 400
loop(Parent, Name, State, Mod, Time, HibernateAfterTimeout, Debug) ->
Msg = receive
Input ->
Input
after Time ->
timeout
end,
decode_msg(Msg, Parent, Name, State, Mod, Time, HibernateAfterTimeout, Debug, false).
it helps you to understand the parameter Timeout
Upvotes: 2
Reputation: 121000
To initiate timeout handling from gen_server:handle_call/3
callback, this callback has to be called in the first place. Your Return={reply,State,State,5000},
is not executed at all.
Instead, if you want to “launch the server and would not use gen_server:call/2
for 5 seconds then handle_info/2
would be called”, you might return {ok,State,Timeout}
tuple from gen_server:init/1
callback.
init(Data)->
{ok,33,5000}.
You cannot set the different timeouts for different calls and casts. As stated by Alexey Romanov in comments,
Having different timeouts for different types of messages just isn’t something any
gen_*
behavior does and would have to be simulated by maintaining them inside state.
If one returns {reply,State,Timeout}
tuple from any handle_call/3
/handle_cast/2
, the timeout will be triggered if the mailbox of this process is empty after Timeout
.
Upvotes: 6