Don's receive any message after handle_call timeout

From GenServer — Elixir v1.13.1

If the caller catches the failure and continues running, and the server is just late with the reply, it may arrive at any time later into the caller’s message queue. The caller must in this case be prepared for this and discard any such garbage messages that are two-element tuples with a reference as the first element.

Does this mean the GenSever will still send response back eventually after timeout?

But from my test, I don’s see any response back.

defmodule ProcessThatTimesout do
  use GenServer

  def start_link() do
    GenServer.start_link(__MODULE__, nil)
  end

  def init(opts), do: {:ok, opts}

  def handle_call(:long_call, _from, state) do
    :timer.sleep(2000)
    IO.inspect("wake and send message back")
    {:reply, "I am wake up now hhh", state}
  end
end

iex(8)> {:ok, pid} = ProcessThatTimesout.start_link()
{:ok, #PID<0.248.0>}
iex(9)> :gen_server.call pid, :long_call, 1000
** (exit) exited in: :gen_server.call(#PID<0.248.0>, :long_call, 1000)
** (EXIT) time out
(stdlib 3.16.1) gen_server.erl:247: :gen_server.call/3
“wake and send message back”

From the message, the hand_call eventually returned and I expected got response from iex.
But iex flush return nothing.
iex(9)> flush
:ok

Thanks! :smiley:

This is the key part here. You’ll need a try block to catch the error and continue on.

OTP 24 introduced means of filtering out late replies after the caller cought a timeout.

1 Like

Thanks !

iex process will catch exit by default.

Interactive Elixir (1.12.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> self()
#PID<0.167.0>
iex(2)> exit(1)
** (exit) 1

iex(2)> self()
#PID<0.167.0>

1 Like

On this computer I have an old Elixir 1.8 and it does do what you expect:

iex(4)> {:ok, pid} = ProcessThatTimesout.start_link
{:ok, #PID<0.121.0>}
iex(5)> self()
#PID<0.99.0>
iex(6)>  :gen_server.call pid, :long_call, 1000
** (exit) exited in: :gen_server.call(#PID<0.121.0>, :long_call, 1000)
    ** (EXIT) time out
    (stdlib) gen_server.erl:223: :gen_server.call/3
iex(6)> s"wake and send message back"
iex(6)> elf
#PID<0.99.0>
iex(7)> self
#PID<0.99.0>
iex(8)> flush
{#Reference<0.2112097019.3803971586.260687>, "I am wake up now hhh"}
:ok

But as @LostKobrakai said OTP 24 is now using aliases.