diff options
author | José Valim <jose.valim@plataformatec.com.br> | 2018-05-07 21:24:22 +0200 |
---|---|---|
committer | José Valim <jose.valim@plataformatec.com.br> | 2018-05-07 21:25:31 +0200 |
commit | 762b5c0870969fcb0341b3b0954e5dd03ec537c1 (patch) | |
tree | 89bf3197b522155fa2245c68762fdf77e59e17e0 | |
parent | a9f1be07ca1a939739bd013f100686c8cf81432a (diff) | |
download | elixir-762b5c0870969fcb0341b3b0954e5dd03ec537c1.tar.gz |
Count children restarting on exit in DynamicSupervisor max_children
Closes #7655
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
-rw-r--r-- | lib/elixir/lib/dynamic_supervisor.ex | 22 | ||||
-rw-r--r-- | lib/elixir/test/elixir/dynamic_supervisor_test.exs | 17 |
2 files changed, 25 insertions, 14 deletions
diff --git a/lib/elixir/lib/dynamic_supervisor.ex b/lib/elixir/lib/dynamic_supervisor.ex index 2e5a725fc..8efbc924b 100644 --- a/lib/elixir/lib/dynamic_supervisor.ex +++ b/lib/elixir/lib/dynamic_supervisor.ex @@ -179,7 +179,6 @@ defmodule DynamicSupervisor do :max_restarts, :max_seconds, children: %{}, - dynamic: 0, restarts: [] ] @@ -625,10 +624,10 @@ defmodule DynamicSupervisor do end def handle_call({:start_child, child}, _from, state) do - %{dynamic: dynamic, max_children: max_children} = state + %{children: children, max_children: max_children} = state - if dynamic < max_children do - handle_start_child(child, %{state | dynamic: dynamic + 1}) + if map_size(children) < max_children do + handle_start_child(child, state) else {:reply, {:error, :max_children}, state} end @@ -645,7 +644,7 @@ defmodule DynamicSupervisor do {:reply, reply, save_child(pid, mfa, restart, shutdown, type, modules, state)} _ -> - {:reply, reply, update_in(state.dynamic, &(&1 - 1))} + {:reply, reply, state} end end @@ -664,14 +663,14 @@ defmodule DynamicSupervisor do end end - defp save_child(pid, {m, f, _}, :temporary, shutdown, type, modules, state) do - put_in(state.children[pid], {{m, f, :undefined}, :temporary, shutdown, type, modules}) - end - defp save_child(pid, mfa, restart, shutdown, type, modules, state) do + mfa = mfa_for_restart(mfa, restart) put_in(state.children[pid], {mfa, restart, shutdown, type, modules}) end + defp mfa_for_restart({m, f, _}, :temporary), do: {m, f, :undefined} + defp mfa_for_restart(mfa, _), do: mfa + defp exit_reason(:exit, reason, _), do: reason defp exit_reason(:error, reason, stack), do: {reason, stack} defp exit_reason(:throw, value, stack), do: {{:nocatch, value}, stack} @@ -888,9 +887,8 @@ defmodule DynamicSupervisor do {:ok, delete_child(pid, state)} end - defp delete_child(pid, state) do - %{children: children, dynamic: dynamic} = state - %{state | children: Map.delete(children, pid), dynamic: dynamic - 1} + defp delete_child(pid, %{children: children} = state) do + %{state | children: Map.delete(children, pid)} end defp restart_child(pid, child, state) do diff --git a/lib/elixir/test/elixir/dynamic_supervisor_test.exs b/lib/elixir/test/elixir/dynamic_supervisor_test.exs index cf741295a..b240204b7 100644 --- a/lib/elixir/test/elixir/dynamic_supervisor_test.exs +++ b/lib/elixir/test/elixir/dynamic_supervisor_test.exs @@ -340,7 +340,7 @@ defmodule DynamicSupervisorTest do assert %{workers: 4, active: 2} = DynamicSupervisor.count_children(pid) end - test "restarting children counted in max_children" do + test "restarting on init children counted in max_children" do child = current_module_worker([:restart, :error], restart: :permanent) opts = [strategy: :one_for_one, max_children: 1, max_restarts: 100_000] {:ok, pid} = DynamicSupervisor.start_link(opts) @@ -353,7 +353,20 @@ defmodule DynamicSupervisorTest do assert {:error, :max_children} = DynamicSupervisor.start_child(pid, child) end - test "restarting a child with extra_args successfully restarts child" do + test "restarting on exit children counted in max_children" do + child = current_module_worker([:ok2], restart: :permanent) + opts = [strategy: :one_for_one, max_children: 1, max_restarts: 100_000] + {:ok, pid} = DynamicSupervisor.start_link(opts) + + assert {:ok, child_pid} = DynamicSupervisor.start_child(pid, child) + assert_kill(child_pid, :shutdown) + assert %{workers: 1, active: 1} = DynamicSupervisor.count_children(pid) + + child = current_module_worker([:ok2], restart: :permanent) + assert {:error, :max_children} = DynamicSupervisor.start_child(pid, child) + end + + test "restarting a child with extra_arguments successfully restarts child" do parent = self() fun = fn -> |