Why does my worker not restart?

818 views
Skip to first unread message

brian law

unread,
Dec 19, 2015, 11:07:06 PM12/19/15
to elixir-lang-talk
When doing a pop on my Stack which has no elements the process crashes (expected), but it doesn't restart even thought the process is started under a Supervisor.

I'm just starting to learn Elixir, could someone explain why this doesn't work or point out any issues with the code below?


iex(41)> {:ok, stack1} = Test.start_child
{:ok, #PID<0.367.0>}
iex(42)> Stack.pop(stack1)

23:03:56.303 [error] GenServer #PID<0.367.0> terminating
** (FunctionClauseError) no function clause matching in Stack.handle_call/3
   
iex(42)> Stack.pop(stack1)
** (exit) exited in: GenServer.call(#PID<0.367.0>, :pop, 5000)
    ** (EXIT) no process
    (elixir) lib/gen_server.ex:544: GenServer.call/3


Module:

defmodule Test do
  use Application
  import Supervisor.Spec, warn: false

  def start(_type, _args) do

    children = [
      worker(Stack, [])
    ]

    opts = [strategy: :simple_one_for_one, name: Test.Supervisor]
    Supervisor.start_link(children, opts)
  end

  def start_child do
    Supervisor.start_child(Test.Supervisor, [])
  end
end


defmodule Stack do
  use GenServer

  def start_link do
    GenServer.start_link(__MODULE__, [], [])
  end

  def pop(pid) do
    GenServer.call(pid, :pop)
  end

  def handle_call(:pop, _from, [h|t]) do
    {:reply, h, t}
  end

end


Ben Wilson

unread,
Dec 19, 2015, 11:30:07 PM12/19/15
to elixir-lang-talk
See the documentation on simple one for one supervisors. They do not by default restart their children. You want to pass restart: :transient to your supervise call.

brian law

unread,
Dec 20, 2015, 12:22:46 AM12/20/15
to elixir-lang-talk
I've added restart: :transient to my worker, but it still doesn't restart.

children = [
   worker(Stack, [], restart: :transient),
]

Ben Wilson

unread,
Dec 20, 2015, 12:27:57 AM12/20/15
to elixir-lang-talk
Ah sorry I wasn't particularly clear. That option goes alongside your strategy: :simple_one_for_one option that's passed to the supervise function.

Take a look through http://elixir-lang.org/docs/v1.0/elixir/Supervisor.Spec.html for further info.

Ben Wilson

unread,
Dec 20, 2015, 12:29:43 AM12/20/15
to elixir-lang-talk
These are options for the Supervisor.start_link function call rather, my bad. If you were building supervisors a different way it would be a supervise call.

José Valim

unread,
Dec 20, 2015, 3:51:08 AM12/20/15
to elixir-l...@googlegroups.com
The pid identifies a single process. Once your process dies, that process/pid is dead.

To see restarts in action you should register the Stack process. Try this:


defmodule Test do
  use Application
  import Supervisor.Spec, warn: false

  def start(_type, _args) do
    children = [
      worker(Stack, [])
    ]

    opts = [strategy: :simple_one_for_one, name: Test.Supervisor]
    Supervisor.start_link(children, opts)
  end

  def start_child do
    Supervisor.start_child(Test.Supervisor, [])
  end
end


defmodule Stack do
  use GenServer

  def start_link(name) do
    GenServer.start_link(__MODULE__, [], name: name)
  end

  def pop(pid) do
    GenServer.call(pid, :pop)
  end

  def handle_call(:pop, _from, [h|t]) do
    {:reply, h, t}
  end
end


And now on IEx:

iex(41)> {:ok, _} = Test.start_child(:foo)
{:ok, #PID<0.367.0>}
iex(42)> Stack.pop(:foo)
iex(42)> Stack.pop(:foo)




José Valim
Skype: jv.ptec
Founder and Director of R&D

--
You received this message because you are subscribed to the Google Groups "elixir-lang-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-ta...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-talk/0acd535c-1e4a-4197-bc5c-7e7cc316f08f%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

James Fish

unread,
Dec 20, 2015, 5:58:34 AM12/20/15
to elixir-l...@googlegroups.com
Ben, I think you are confusing Task.Supervisor with all simple_one_for_one supervisors. The strategy of a supervisor is orthogonal to the restart type of a child. If a restart type is not set for a child it will default to permanent. However the child spec is defined by the Task.Supervisor itself so the restart type is passed as an option. In this specific case the default restart is temporary

On 20 December 2015 at 05:29, Ben Wilson <benwil...@gmail.com> wrote:
These are options for the Supervisor.start_link function call rather, my bad. If you were building supervisors a different way it would be a supervise call.
--
You received this message because you are subscribed to the Google Groups "elixir-lang-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-ta...@googlegroups.com.

brian law

unread,
Dec 20, 2015, 9:47:28 AM12/20/15
to elixir-lang-talk, jose....@plataformatec.com.br
Thanks Jose, it works now!
Reply all
Reply to author
Forward
0 new messages