We have a supervisor structure where one supervisor adds two children dynamically. They are added dynamically because the second child needs to know the pid of the first one.
Now we experience problems when the supervisor is crashing, because the supervisor is not restarted thereafter.
(If one of the children crashes, they are restarted totally fine.)
Edit: We are using Elixir 1.5.1
I could reproduce the problem in a small sample project:
Application
defmodule Sup.Application do
use Application
def start(_type, _args) do
children = [
{Sup.Supervisor, []},
{Dyn.Sup.Supervisor, []}
]
opts = [strategy: :one_for_one, name: SupShit.Supervisor]
Supervisor.start_link(children, opts)
end
end
Dyn.Sup.Supervisor
defmodule Dyn.Sup.Supervisor do
use Supervisor
def start_link(_) do
{:ok, sup} = Supervisor.start_link(__MODULE__, [], name: __MODULE__)
{:ok, worker1} = Supervisor.start_child(sup, worker(Worker, []))
# In our real app there would be another worker which depens on the first one
# but is not neccessary to reproduce the problem
#Supervisor.start_child(sup, worker(Worker2, [worker1]))
end
def init([]) do
Supervisor.init([], strategy: :one_for_one)
end
end
Worker
defmodule Worker do
def start_link(_) do
start_link()
end
def start_link() do
GenServer.start_link(__MODULE__, [])
end
def init(_) do
{:ok, nil}
end
end
Now when using :observer and killing the Dyn.Sup.Supervisor it is not restarted.
I then tried to reproduce this with a supervisor with static children but that was restarted after the crash as expected:
Sup.Supervisor
defmodule Sup.Supervisor do
use Supervisor
def start_link(_) do
Supervisor.start_link(__MODULE__, [], name: __MODULE__)
end
def init([]) do
children = [
worker(Worker, [])
]
supervise(children, strategy: :one_for_one)
end
end
No my question is, is there a problem how we create the dynamic children? Or musn’t they be added in in start_link?