Skip to content

Commit 762b5c0

Browse files
author
José Valim
committed
Count children restarting on exit in DynamicSupervisor max_children
Closes #7655 Signed-off-by: José Valim <[email protected]>
1 parent a9f1be0 commit 762b5c0

File tree

2 files changed

+25
-14
lines changed

2 files changed

+25
-14
lines changed

lib/elixir/lib/dynamic_supervisor.ex

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,6 @@ defmodule DynamicSupervisor do
179179
:max_restarts,
180180
:max_seconds,
181181
children: %{},
182-
dynamic: 0,
183182
restarts: []
184183
]
185184

@@ -625,10 +624,10 @@ defmodule DynamicSupervisor do
625624
end
626625

627626
def handle_call({:start_child, child}, _from, state) do
628-
%{dynamic: dynamic, max_children: max_children} = state
627+
%{children: children, max_children: max_children} = state
629628

630-
if dynamic < max_children do
631-
handle_start_child(child, %{state | dynamic: dynamic + 1})
629+
if map_size(children) < max_children do
630+
handle_start_child(child, state)
632631
else
633632
{:reply, {:error, :max_children}, state}
634633
end
@@ -645,7 +644,7 @@ defmodule DynamicSupervisor do
645644
{:reply, reply, save_child(pid, mfa, restart, shutdown, type, modules, state)}
646645

647646
_ ->
648-
{:reply, reply, update_in(state.dynamic, &(&1 - 1))}
647+
{:reply, reply, state}
649648
end
650649
end
651650

@@ -664,14 +663,14 @@ defmodule DynamicSupervisor do
664663
end
665664
end
666665

667-
defp save_child(pid, {m, f, _}, :temporary, shutdown, type, modules, state) do
668-
put_in(state.children[pid], {{m, f, :undefined}, :temporary, shutdown, type, modules})
669-
end
670-
671666
defp save_child(pid, mfa, restart, shutdown, type, modules, state) do
667+
mfa = mfa_for_restart(mfa, restart)
672668
put_in(state.children[pid], {mfa, restart, shutdown, type, modules})
673669
end
674670

671+
defp mfa_for_restart({m, f, _}, :temporary), do: {m, f, :undefined}
672+
defp mfa_for_restart(mfa, _), do: mfa
673+
675674
defp exit_reason(:exit, reason, _), do: reason
676675
defp exit_reason(:error, reason, stack), do: {reason, stack}
677676
defp exit_reason(:throw, value, stack), do: {{:nocatch, value}, stack}
@@ -888,9 +887,8 @@ defmodule DynamicSupervisor do
888887
{:ok, delete_child(pid, state)}
889888
end
890889

891-
defp delete_child(pid, state) do
892-
%{children: children, dynamic: dynamic} = state
893-
%{state | children: Map.delete(children, pid), dynamic: dynamic - 1}
890+
defp delete_child(pid, %{children: children} = state) do
891+
%{state | children: Map.delete(children, pid)}
894892
end
895893

896894
defp restart_child(pid, child, state) do

lib/elixir/test/elixir/dynamic_supervisor_test.exs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ defmodule DynamicSupervisorTest do
340340
assert %{workers: 4, active: 2} = DynamicSupervisor.count_children(pid)
341341
end
342342

343-
test "restarting children counted in max_children" do
343+
test "restarting on init children counted in max_children" do
344344
child = current_module_worker([:restart, :error], restart: :permanent)
345345
opts = [strategy: :one_for_one, max_children: 1, max_restarts: 100_000]
346346
{:ok, pid} = DynamicSupervisor.start_link(opts)
@@ -353,7 +353,20 @@ defmodule DynamicSupervisorTest do
353353
assert {:error, :max_children} = DynamicSupervisor.start_child(pid, child)
354354
end
355355

356-
test "restarting a child with extra_args successfully restarts child" do
356+
test "restarting on exit children counted in max_children" do
357+
child = current_module_worker([:ok2], restart: :permanent)
358+
opts = [strategy: :one_for_one, max_children: 1, max_restarts: 100_000]
359+
{:ok, pid} = DynamicSupervisor.start_link(opts)
360+
361+
assert {:ok, child_pid} = DynamicSupervisor.start_child(pid, child)
362+
assert_kill(child_pid, :shutdown)
363+
assert %{workers: 1, active: 1} = DynamicSupervisor.count_children(pid)
364+
365+
child = current_module_worker([:ok2], restart: :permanent)
366+
assert {:error, :max_children} = DynamicSupervisor.start_child(pid, child)
367+
end
368+
369+
test "restarting a child with extra_arguments successfully restarts child" do
357370
parent = self()
358371

359372
fun = fn ->

0 commit comments

Comments
 (0)