So I had a play around with this:
A simple server:
defmodule Tracetest.Server do
use GenServer
def start_link(arg) do
GenServer.start_link(__MODULE__, [arg])
end
@impl true
def init([arg]) do
{:ok, :some_state, {:continue, arg}}
end
@impl true
def handle_continue(_, state) do
{:noreply, state}
end
end
The test:
test "can know when handle_continue finished" do
:erlang.trace(:new, true, [:call, :return_to])
:erlang.trace_pattern({Tracetest.Server, :handle_continue, 2}, true, [:local])
{:ok, pid} = Tracetest.Server.start_link(:foo)
assert_receive {:trace, ^pid, :call,
{Tracetest.Server, :handle_continue, [:foo, :some_state]}}
assert_receive {:trace, ^pid, :return_to, {:gen_server, :try_dispatch, 4}}
assert true == true
end
I setup the same tracing calls in the iex console, started the server there, and ran flush to see what trace messages got received. There were only two so it was straightforward to match on them. I am sure your real code is a lot more complicated than this but perhaps just waiting till the method had been called rather than a return would be enough to avoid the race condition.






















