diff options
author | Siri Hansen <[email protected]> | 2011-12-15 11:57:30 +0100 |
---|---|---|
committer | Siri Hansen <[email protected]> | 2012-03-05 11:22:13 +0100 |
commit | e6e31791abf090fe7e0bd3e5970b44830d087c4a (patch) | |
tree | d2a6f3dd000d2a1ce843d5c687498b9d43cc4879 /lib/stdlib/test/supervisor_deadlock.erl | |
parent | d1e67d51a6d754e5a055c81c9d7447e0d87e982f (diff) | |
download | otp-e6e31791abf090fe7e0bd3e5970b44830d087c4a.tar.gz otp-e6e31791abf090fe7e0bd3e5970b44830d087c4a.tar.bz2 otp-e6e31791abf090fe7e0bd3e5970b44830d087c4a.zip |
Leave control back to gen_server during supervisor's restart loop
When an attempt to restart a child failed, supervisor would earlier
keep the execution flow and try to restart the child over and over
again until it either succeeded or the restart frequency limit was
reached. If none of these happened, supervisor would hang forever in
this loop.
This commit adds a timer of 0 ms where the control is left back to the
gen_server which implements the supervisor. This way any incoming
request to the supervisor will be handled - which could help breaking
the infinite loop - e.g. shutdown request for the supervisor or for
the problematic child.
This introduces some incompatibilities in stdlib due to new return
values from supervisor:
* restart_child/2 can now return {error,restarting}
* delete_child/2 can now return {error,restarting}
* which_children/1 returns a list of {Id,Child,Type,Mods},
where Child, in addition to the old pid() or 'undefined',
now also can be 'restarting'.
Diffstat (limited to 'lib/stdlib/test/supervisor_deadlock.erl')
-rw-r--r-- | lib/stdlib/test/supervisor_deadlock.erl | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/lib/stdlib/test/supervisor_deadlock.erl b/lib/stdlib/test/supervisor_deadlock.erl new file mode 100644 index 0000000000..288547a972 --- /dev/null +++ b/lib/stdlib/test/supervisor_deadlock.erl @@ -0,0 +1,45 @@ +-module(supervisor_deadlock). +-compile(export_all). + + +%%%----------------------------------------------------------------- +%%% gen_server callbacks +init([child]) -> + case ets:lookup(supervisor_deadlock,fail_start) of + [{fail_start, false}] -> + %% we must not fail on the first init, otherwise supervisor + %% terminates immediately + {ok, []}; + [{fail_start, true}] -> + %% Restart frequency is MaxR=8, MaxT=10, so this will + %% ensure that restart intensity is not reached -> restart + %% loop + timer:sleep(2000), % NOTE: this could be a gen_server call timeout + + {stop, error} + end. + +handle_call(_Req, _From, State) -> + {reply, ok, State}. + +%% Force a restart +handle_cast(restart, State) -> + {stop, error, State}. + +handle_info(_Msg, State) -> + {noreply, State}. + +terminate(_Reason, _State) -> + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + + +%%%----------------------------------------------------------------- +%%% Start child +start_child() -> + gen_server:start_link({local, ?MODULE}, ?MODULE, [child], []). + +restart_child() -> + gen_server:cast(supervisor_deadlock, restart). |