Just ran into a nasty little bug that I thought I would share to see if there was some reasonable warning that could be made.
Here is an example IEx session:
```
Erlang/OTP 20 [erts-9.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Interactive Elixir (1.6.0-dev) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> defmodule MyServer do
...(1)> use GenServer
...(1)>
...(1)> def handle_call(:quit, from, _) do
...(1)> GenServer.reply(from, :ok)
...(1)> GenServer.stop(self(), :normal)
...(1)> end
...(1)>
...(1)> def handle_call(:hello, _from, _) do
...(1)> IO.inspect :world
...(1)> {:reply, :ok, []}
...(1)> end
...(1)> end
{
:module,
MyServer,
<<70, 79, 82, 49, 0, 0, 14, 0, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 1, 189,
0, 0, 0, 46, 15, 69, 108, 105, 120, 105, 114, 46, 77, 121, 83, 101, 114,
118, 101, 114, 8, 95, 95, 105, 110, 102, 111, ...>>,
{:handle_call, 3}
}
iex(2)> {:ok, pid} = GenServer.start_link(MyServer, [])
{:ok, #PID<0.103.0>}
iex(3)> GenServer.call(pid, :hello)
:world
:ok
iex(4)> GenServer.call(pid, :quit)
:ok
iex(5)> GenServer.call(pid, :hello)
** (exit) exited in: GenServer.call(#PID<0.103.0>, :hello, 5000)
** (EXIT) time out
(elixir) lib/gen_server.ex:790: GenServer.call/3
iex(5)> Process.alive?(pid)
true
```
Here I made a simple GenServer that responds to `:hello` and `:quit`. The code may look innocuous at first glance, but the GenServer deadlocks on the `:quit` call because `GenServer.stop` is synchronous and blocking by default. The correct way to implement this is by returning a stop tuple of course, however I was surprised that no warning or error was raised.
By contrast, a GenServer will crash if it tries to call itself:
```15:23:25.018 [error] GenServer #PID<0.97.0> terminating
** (stop) exited in: GenServer.call(#PID<0.97.0>, :call_self, 5000)
** (EXIT) process attempted to call itself
(elixir) lib/gen_server.ex:783: GenServer.call/3
(stdlib) gen_server.erl:636: :gen_server.try_handle_call/4
(stdlib) gen_server.erl:665: :gen_server.handle_msg/6
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Last message (from #PID<0.84.0>): :call_self
State: []
Client #PID<0.84.0> is alive
(stdlib) gen.erl:169: :gen.do_call/4
(elixir) lib/gen_server.ex:787: GenServer.call/3
(stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
(elixir) src/elixir.erl:233: :elixir.eval_forms/4
(iex) lib/iex/evaluator.ex:245: IEx.Evaluator.handle_eval/5
(iex) lib/iex/evaluator.ex:225: IEx.Evaluator.do_eval/3
(iex) lib/iex/evaluator.ex:203: IEx.Evaluator.eval/3
(iex) lib/iex/evaluator.ex:89: IEx.Evaluator.loop/1
```
`GenServer.stop` involves a middleman process from what I can see which stops this deadlock prevention from saving us in our original case.
Anyways, it would be nice to have Elixir (or Erlang) warn us when we are doing this. I could see this being implemented a few different places but wanted to put the problem out there to see what people thought