From 19ca18fa2425d592e7c340f453b6d44c22e00f9b Mon Sep 17 00:00:00 2001 From: Filipe David Manana Date: Sun, 27 Mar 2011 17:51:59 +0100 Subject: Fix issue with temporary children introduced by OTP-9064 The temporary child specs are never removed from the supervisor's state, and have they're MFA component set to {M, F, undefined} instead of the MFA passed in the supervisor:start_child/2 call. Subsequent calls to supervisor:restart_child/2 may crash. Stack trace example: {badarg,[{erlang,apply,[gen_server,start_link,undefined]}, {supervisor,do_start_child,2},{supervisor,handle_call,3}, {gen_server,handle_msg,5}, {proc_lib,init_p_do_apply,3}]} --- lib/stdlib/src/supervisor.erl | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/stdlib/src') diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl index 3c5800effa..b511545b96 100644 --- a/lib/stdlib/src/supervisor.erl +++ b/lib/stdlib/src/supervisor.erl @@ -817,8 +817,12 @@ state_del_child(Child, State) -> NChildren = del_child(Child#child.name, State#state.children), State#state{children = NChildren}. +del_child(Name, [Ch|Chs]) when Ch#child.name =:= Name, Ch#child.restart_type =:= temporary -> + [Chs]; del_child(Name, [Ch|Chs]) when Ch#child.name =:= Name -> [Ch#child{pid = undefined} | Chs]; +del_child(Pid, [Ch|Chs]) when Ch#child.pid =:= Pid, Ch#child.restart_type =:= temporary -> + [Chs]; del_child(Pid, [Ch|Chs]) when Ch#child.pid =:= Pid -> [Ch#child{pid = undefined} | Chs]; del_child(Name, [Ch|Chs]) -> -- cgit v1.2.3 From 12b417a1cb28799f78ec911bc1dc9dfdb0af6fea Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Thu, 31 Mar 2011 18:00:55 +0200 Subject: Completed bug fix "temporary child specs should not be kept when child terminates" and improved test suite The bug fix supplied by Filipe David Manana did not cover all possible ways that a process may be terminated as for instance with supervisor:terminate_child. Also there was a bug in the base case of the patch returning a list of a list instead of only the list. Added a timeout for the test cases, eliminated unnecessary sleeps, improved code. --- lib/stdlib/src/supervisor.erl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'lib/stdlib/src') diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl index b511545b96..368dc2e3e5 100644 --- a/lib/stdlib/src/supervisor.erl +++ b/lib/stdlib/src/supervisor.erl @@ -344,8 +344,12 @@ handle_call({delete_child, Name}, _From, State) -> handle_call({terminate_child, Name}, _From, State) -> case get_child(Name, State) of {value, Child} -> - NChild = do_terminate(Child, State#state.name), - {reply, ok, replace_child(NChild, State)}; + case do_terminate(Child, State#state.name) of + #child{restart_type = temporary} = NChild -> + {reply, ok, state_del_child(NChild, State)}; + NChild -> + {reply, ok, replace_child(NChild, State)} + end; _ -> {reply, {error, not_found}, State} end; @@ -818,11 +822,11 @@ state_del_child(Child, State) -> State#state{children = NChildren}. del_child(Name, [Ch|Chs]) when Ch#child.name =:= Name, Ch#child.restart_type =:= temporary -> - [Chs]; + Chs; del_child(Name, [Ch|Chs]) when Ch#child.name =:= Name -> [Ch#child{pid = undefined} | Chs]; del_child(Pid, [Ch|Chs]) when Ch#child.pid =:= Pid, Ch#child.restart_type =:= temporary -> - [Chs]; + Chs; del_child(Pid, [Ch|Chs]) when Ch#child.pid =:= Pid -> [Ch#child{pid = undefined} | Chs]; del_child(Name, [Ch|Chs]) -> -- cgit v1.2.3