summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon MacMullen <simon@rabbitmq.com>2011-07-18 14:50:44 +0100
committerSimon MacMullen <simon@rabbitmq.com>2011-07-18 14:50:44 +0100
commita140aab76627a794270dbae6cca0bfe66bd1b97f (patch)
tree0f4e8738c71fd1f71a77b887e44cf8b457d9651a
parentfb1f332d7135388d4abcb88adba9dac1b322e671 (diff)
downloadrabbitmq-server-a140aab76627a794270dbae6cca0bfe66bd1b97f.tar.gz
If start_child is called twice in a row we used to hang. Um, that's not good. Fix.
-rw-r--r--src/mirrored_supervisor.erl17
-rw-r--r--src/mirrored_supervisor_tests.erl6
2 files changed, 16 insertions, 7 deletions
diff --git a/src/mirrored_supervisor.erl b/src/mirrored_supervisor.erl
index 09d38630..78399b84 100644
--- a/src/mirrored_supervisor.erl
+++ b/src/mirrored_supervisor.erl
@@ -391,22 +391,25 @@ demonitor_all_peers(#state{peer_monitors = Peers}) ->
[erlang:demonitor(Ref) || Ref <- sets:to_list(Peers)].
maybe_start(Delegate, ChildSpec) ->
- case mnesia:transaction(fun() -> check_start(ChildSpec) end) of
+ case mnesia:transaction(fun() -> check_start(Delegate, ChildSpec) end) of
{atomic, start} -> start(Delegate, ChildSpec);
{atomic, Pid} -> {ok, Pid}
end.
-check_start(ChildSpec) ->
+check_start(Delegate, ChildSpec) ->
case mnesia:wread({?TABLE, id(ChildSpec)}) of
[] -> write(ChildSpec),
start;
[S] -> #mirrored_sup_childspec{id = Id,
mirroring_pid = Pid} = S,
- case supervisor(Pid) of
- dead -> delete(ChildSpec),
- write(ChildSpec),
- start;
- Delegate -> child(Delegate, Id)
+ case self() of
+ Pid -> child(Delegate, Id);
+ _ -> case supervisor(Pid) of
+ dead -> delete(ChildSpec),
+ write(ChildSpec),
+ start;
+ Delegate0 -> child(Delegate0, Id)
+ end
end
end.
diff --git a/src/mirrored_supervisor_tests.erl b/src/mirrored_supervisor_tests.erl
index 51d3ea0d..b052e255 100644
--- a/src/mirrored_supervisor_tests.erl
+++ b/src/mirrored_supervisor_tests.erl
@@ -37,6 +37,7 @@ all_tests() ->
passed = test_childspecs_at_init(),
passed = test_anonymous_supervisors(),
passed = test_no_migration_on_shutdown(),
+ passed = test_start_idempotence(),
passed.
%% Simplest test
@@ -131,6 +132,11 @@ test_no_migration_on_shutdown() ->
timer:sleep(1000)
end, [evil, good]).
+test_start_idempotence() ->
+ with_sups(fun([A]) ->
+ mirrored_supervisor:start_child(a, childspec(worker)),
+ mirrored_supervisor:start_child(a, childspec(worker))
+ end, [a]).
%% ---------------------------------------------------------------------------