diff options
| author | Emile Joubert <emile@rabbitmq.com> | 2011-11-07 13:07:30 +0000 |
|---|---|---|
| committer | Emile Joubert <emile@rabbitmq.com> | 2011-11-07 13:07:30 +0000 |
| commit | bd54ca5fe425d8fb316987f8db991b156f514221 (patch) | |
| tree | c380f2ef705d3444da2ef3856953940642c0c9f3 | |
| parent | 6c5e554fc596ef3149a32a7e9335117d58b125a0 (diff) | |
| parent | d82d34cb379cc6c00f02b42288e176a298f696b6 (diff) | |
| download | rabbitmq-server-git-bd54ca5fe425d8fb316987f8db991b156f514221.tar.gz | |
Merged bug24534 into default
| -rw-r--r-- | src/supervisor2.erl | 72 |
1 files changed, 65 insertions, 7 deletions
diff --git a/src/supervisor2.erl b/src/supervisor2.erl index 405949efc8..f75da87221 100644 --- a/src/supervisor2.erl +++ b/src/supervisor2.erl @@ -649,15 +649,69 @@ terminate_children([], _SupName, Res) -> Res. terminate_simple_children(Child, Dynamics, SupName) -> - dict:fold(fun (Pid, _Args, _Any) -> - do_terminate(Child#child{pid = Pid}, SupName) - end, ok, Dynamics), + Pids = dict:fold(fun (Pid, _Args, Pids) -> + erlang:monitor(process, Pid), + unlink(Pid), + exit(Pid, child_exit_reason(Child)), + [Pid | Pids] + end, [], Dynamics), + TimeoutMsg = {timeout, make_ref()}, + TRef = timeout_start(Child, TimeoutMsg), + {Replies, Timedout} = + lists:foldl( + fun (_Pid, {Replies, Timedout}) -> + {Reply, Timedout1} = + receive + TimeoutMsg -> + Remaining = Pids -- [P || {P, _} <- Replies], + [exit(P, kill) || P <- Remaining], + receive {'DOWN', _MRef, process, Pid, Reason} -> + {{error, Reason}, true} + end; + {'DOWN', _MRef, process, Pid, Reason} -> + {child_res(Child, Reason, Timedout), Timedout}; + {'EXIT', Pid, Reason} -> + receive {'DOWN', _MRef, process, Pid, _} -> + {{error, Reason}, Timedout} + end + end, + {[{Pid, Reply} | Replies], Timedout1} + end, {[], false}, Pids), + timeout_stop(Child, TRef, TimeoutMsg, Timedout), + ReportError = shutdown_error_reporter(SupName), + [case Reply of + {_Pid, ok} -> ok; + {Pid, {error, R}} -> ReportError(R, Child#child{pid = Pid}) + end || Reply <- Replies], + ok. + +child_exit_reason(#child{shutdown = brutal_kill}) -> kill; +child_exit_reason(#child{}) -> shutdown. + +child_res(#child{shutdown=brutal_kill}, killed, false) -> ok; +child_res(#child{}, shutdown, false) -> ok; +child_res(#child{restart_type=permanent}, normal, false) -> {error, normal}; +child_res(#child{restart_type={permanent,_}},normal, false) -> {error, normal}; +child_res(#child{}, normal, false) -> ok; +child_res(#child{}, R, _) -> {error, R}. + +timeout_start(#child{shutdown = Time}, Msg) when is_integer(Time) -> + erlang:send_after(Time, self(), Msg); +timeout_start(#child{}, _Msg) -> + ok. + +timeout_stop(#child{shutdown = Time}, TRef, Msg, false) when is_integer(Time) -> + erlang:cancel_timer(TRef), + receive + Msg -> ok + after + 0 -> ok + end; +timeout_stop(#child{}, ok, _Msg, _Timedout) -> ok. do_terminate(Child, SupName) when Child#child.pid =/= undefined -> - ReportError = fun (Reason) -> - report_error(shutdown_error, Reason, Child, SupName) - end, + ReportError = shutdown_error_reporter(SupName), case shutdown(Child#child.pid, Child#child.shutdown) of ok -> ok; @@ -668,7 +722,7 @@ do_terminate(Child, SupName) when Child#child.pid =/= undefined -> _ -> ok end; {error, OtherReason} -> - ReportError(OtherReason) + ReportError(OtherReason, Child) end, Child#child{pid = undefined}; do_terminate(Child, _SupName) -> @@ -998,6 +1052,10 @@ report_error(Error, Reason, Child, SupName) -> {offender, extract_child(Child)}], error_logger:error_report(supervisor_report, ErrorMsg). +shutdown_error_reporter(SupName) -> + fun(Reason, Child) -> + report_error(shutdown_error, Reason, Child, SupName) + end. extract_child(Child) -> [{pid, Child#child.pid}, |
