[erlang-questions] The Danger of gen:server timeout

Jesper Louis Andersen jesper.louis.andersen@REDACTED
Fri Jun 2 13:59:23 CEST 2017


Here is the crux of what you are toying with: Erlang has two kinds of
timeouts: idle timeouts and point-in-time timeouts. The timeouts you can
set in a gen_server are idle timeouts, so they are implemented basically as

receive
  ...
after Timeout ->
  ...
end

What this means is that any message which arrives in the mailbox cancels
the timeout. In particular, your sys:get_state/1 call invokes such a
message, resetting the timeout. If you want a point-in-time timeout, there
is another tool for this: erlang:send_after/3. It will deliver a message
through another timer system and even if the process is active, you will
get the timer in a relatively timely fashion. You are not guaranteed to get
the timer precisely at the point if the system is heavily loaded, but
usually you get it within a couple of ms of where you want at worst. This
is the essence of being soft-realtime, amont other things.

The gen_server timeouts are nice to use for the situation where idling
means you can do some janitorial work in your process or do a hibernation.
I often have some janitorial work that runs either on a counter (every 100
message) and also on an idle timer (20 seconds has passed with no message).

On Fri, Jun 2, 2017 at 11:09 AM Ben Murphy <benmmurphy@REDACTED> wrote:

> So a bunch of gen_server:* methods allow you to return a timeout
> value. So if you were thinking about how this would be implemented you
> would expect if elapsed time >Timeout it would send a timeout message
> to your process. This is true. However, if elapsed time > much greater
> than Timeout then a timeout message could be sent to your process :/
> How is this possible?
>
> If your process receives a system message before the timeout then the
> timeout is reset without considering how long you have waited before
> receiving a system message. For example: you could be waiting 1 month
> for a timeout then after 20 days someone did sys:get_state on your
> process then you are waiting another 1 month for your timeout..
>
> -module(wtf).
> -behaviour(gen_server).
>
> -export([init/1, code_change/3, handle_call/3, handle_cast/2,
> handle_info/2, terminate/2]).
>
> init(_Args) ->
>   TS = erlang:timestamp(),
>   io:format("init: ~p~n", [TS]),
>   {ok, TS, 30 * 1000}.
>
>
> handle_info(Message, TS) ->
>   io:format(user, "handle info :~p ~p ~n", [Message, erlang:timestamp()]),
>   Now = erlang:timestamp(),
>   io:format(user, "difference: ~p ~n", [timer:now_diff(Now, TS)]),
>   {noreply, TS}.
>
>
> code_change(_1, _2, _3) ->
>   throw(wtf).
> handle_call(_1, _2, _3) ->
>   throw(wtf).
> handle_cast(_1, _2) ->
>   throw(wtf).
> terminate(_1, _2) ->
>    ok.
>
> Erlang/OTP 19 [erts-8.0] [source] [64-bit] [smp:4:4]
> [async-threads:10] [hipe] [kernel-poll:false]
>
> Eshell V8.0  (abort with ^G)
> 1> {ok, Pid} =  gen_server:start_link(wtf, [], []).
> init: {1496,394234,956218}
> {ok,<0.59.0>}
> 2> sys:get_state(Pid).
> {1496,394234,956218}
> 3> handle info :timeout {1496,394279,244306}
> difference: 44288466
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20170602/532d5926/attachment.htm>


More information about the erlang-questions mailing list