summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosé Valim <jose.valim@plataformatec.com.br>2018-05-07 21:24:22 +0200
committerJosé Valim <jose.valim@plataformatec.com.br>2018-05-07 21:25:31 +0200
commit762b5c0870969fcb0341b3b0954e5dd03ec537c1 (patch)
tree89bf3197b522155fa2245c68762fdf77e59e17e0
parenta9f1be07ca1a939739bd013f100686c8cf81432a (diff)
downloadelixir-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.ex22
-rw-r--r--lib/elixir/test/elixir/dynamic_supervisor_test.exs17
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 ->