aboutsummaryrefslogtreecommitdiffstats
path: root/lib/sasl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sasl')
-rw-r--r--lib/sasl/doc/src/systools.xml10
-rw-r--r--lib/sasl/src/release_handler_1.erl107
-rw-r--r--lib/sasl/src/systools_lib.erl7
-rw-r--r--lib/sasl/src/systools_make.erl174
-rw-r--r--lib/sasl/src/systools_relup.erl68
-rw-r--r--lib/sasl/test/release_handler_SUITE.erl25
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/Makefile.src16
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/ebin/dummy.app7
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_app.erl9
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_server.erl56
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_sup.erl15
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_sup_2.erl15
-rw-r--r--lib/sasl/test/systools_SUITE.erl41
13 files changed, 423 insertions, 127 deletions
diff --git a/lib/sasl/doc/src/systools.xml b/lib/sasl/doc/src/systools.xml
index 883c9c372b..8c1c327d74 100644
--- a/lib/sasl/doc/src/systools.xml
+++ b/lib/sasl/doc/src/systools.xml
@@ -45,7 +45,8 @@
<v>Name = string()</v>
<v>UpFrom = DownTo = [Name | {Name,Descr}]</v>
<v>&nbsp;Descr = term()</v>
- <v>Opt = {path,[Dir]} | restart_emulator | silent | noexec | {outdir,Dir}</v>
+ <v>Opt = {path,[Dir]} | restart_emulator | silent | noexec | {outdir,Dir}
+ | warnings_as_errors</v>
<v>&nbsp;Dir = string()</v>
<v>Result = ok | error | {ok,Relup,Module,Warnings} | {error,Module,Error}</v>
<v>&nbsp;Relup - see relup(4)</v>
@@ -122,6 +123,8 @@
<p>If the option <c>noexec</c> is provided, the function returns
the same values as for <c>silent</c> but no <c>relup</c> file
is created.</p>
+ <p>If the option <c>warnings_as_errors</c> is provided, warnings
+ are treated as errors.</p>
</desc>
</func>
<func>
@@ -130,7 +133,8 @@
<fsummary>Generate a boot script <c>.script/.boot</c>.</fsummary>
<type>
<v>Name = string()</v>
- <v>Opt = src_tests | {path,[Dir]} | local | {variables,[Var]} | exref | {exref,[App]}] | silent | {outdir,Dir}</v>
+ <v>Opt = src_tests | {path,[Dir]} | local | {variables,[Var]} | exref | {exref,[App]}]
+ | silent | {outdir,Dir} | warnings_as_errors</v>
<v>&nbsp;Dir = string()</v>
<v>&nbsp;Var = {VarName,Prefix}</v>
<v>&nbsp;&nbsp;VarName = Prefix = string()</v>
@@ -232,6 +236,8 @@
Warnings and errors can be converted to strings by calling
<c>Module:format_warning(Warnings)</c> or
<c>Module:format_error(Error)</c>.</p>
+ <p>If the option <c>warnings_as_errors</c> is provided, warnings
+ are treated as errors.</p>
</desc>
</func>
<func>
diff --git a/lib/sasl/src/release_handler_1.erl b/lib/sasl/src/release_handler_1.erl
index ef95606bb5..8d0baf3ab1 100644
--- a/lib/sasl/src/release_handler_1.erl
+++ b/lib/sasl/src/release_handler_1.erl
@@ -21,7 +21,7 @@
%% External exports
-export([eval_script/1, eval_script/5,
check_script/2, check_old_processes/2]).
--export([get_current_vsn/1]). %% exported because used in a test case
+-export([get_current_vsn/1, get_supervised_procs/0]). %% exported because used in a test case
-record(eval_state, {bins = [], stopped = [], suspended = [], apps = [],
libdirs, unpurged = [], vsns = [], newlibs = [],
@@ -493,6 +493,19 @@ start(Procs) ->
%% supervisor module, we should load the new version, and then
%% delete the old. Then we should perform the start changes
%% manually, by adding/deleting children.
+%%
+%% Recent changes to this code cause the upgrade error out and
+%% log the case where a suspended supervisor has which_children
+%% called against it. This retains the behavior of causing a VM
+%% restart to the *old* version of a release but has the
+%% advantage of logging the pid and supervisor that had the
+%% issue.
+%%
+%% A second case where this can occur is if a child spec is
+%% incorrect and get_modules is called against a process that
+%% can't respond to the gen:call. Again an error is logged,
+%% an error returned and a VM restart is issued.
+%%
%% Returns: [{SuperPid, ChildName, ChildPid, Mods}]
%%-----------------------------------------------------------------
%% OTP-3452. For each application the first item contains the pid
@@ -502,49 +515,81 @@ start(Procs) ->
get_supervised_procs() ->
lists:foldl(
fun(Application, Procs) ->
- case application_controller:get_master(Application) of
- Pid when is_pid(Pid) ->
- {Root, _AppMod} = application_master:get_child(Pid),
- case get_supervisor_module(Root) of
- {ok, SupMod} ->
- get_procs(supervisor:which_children(Root),
- Root) ++
- [{undefined, undefined, Root, [SupMod]} |
- Procs];
- {error, _} ->
- error_logger:error_msg("release_handler: "
- "cannot find top "
- "supervisor for "
- "application ~w~n",
- [Application]),
- get_procs(supervisor:which_children(Root),
- Root) ++ Procs
- end;
- _ -> Procs
- end
+ get_master_procs(Application,
+ Procs,
+ application_controller:get_master(Application))
end,
[],
- lists:map(fun({Application, _Name, _Vsn}) ->
- Application
- end,
- application:which_applications())).
+ get_application_names()).
+
+get_supervised_procs(_, Root, Procs, {ok, SupMod}) ->
+ get_procs(maybe_supervisor_which_children(get_proc_state(Root), SupMod, Root), Root) ++
+ [{undefined, undefined, Root, [SupMod]} | Procs];
+get_supervised_procs(Application, Root, Procs, {error, _}) ->
+ error_logger:error_msg("release_handler: cannot find top supervisor for "
+ "application ~w~n", [Application]),
+ get_procs(maybe_supervisor_which_children(get_proc_state(Root), Application, Root), Root) ++ Procs.
+
+get_application_names() ->
+ lists:map(fun({Application, _Name, _Vsn}) ->
+ Application
+ end,
+ application:which_applications()).
+
+get_master_procs(Application, Procs, Pid) when is_pid(Pid) ->
+ {Root, _AppMod} = application_master:get_child(Pid),
+ get_supervised_procs(Application, Root, Procs, get_supervisor_module(Root));
+get_master_procs(_, Procs, _) ->
+ Procs.
get_procs([{Name, Pid, worker, dynamic} | T], Sup) when is_pid(Pid) ->
- Mods = get_dynamic_mods(Pid),
+ Mods = maybe_get_dynamic_mods(Name, Pid),
[{Sup, Name, Pid, Mods} | get_procs(T, Sup)];
get_procs([{Name, Pid, worker, Mods} | T], Sup) when is_pid(Pid), is_list(Mods) ->
[{Sup, Name, Pid, Mods} | get_procs(T, Sup)];
get_procs([{Name, Pid, supervisor, Mods} | T], Sup) when is_pid(Pid) ->
- [{Sup, Name, Pid, Mods} | get_procs(T, Sup)] ++
- get_procs(supervisor:which_children(Pid), Pid);
+ [{Sup, Name, Pid, Mods} | get_procs(T, Sup)] ++
+ get_procs(maybe_supervisor_which_children(get_proc_state(Pid), Name, Pid), Pid);
get_procs([_H | T], Sup) ->
get_procs(T, Sup);
get_procs(_, _Sup) ->
[].
-get_dynamic_mods(Pid) ->
- {ok,Res} = gen:call(Pid, self(), get_modules),
- Res.
+get_proc_state(Proc) ->
+ {status, _, {module, _}, [_, State, _, _, _]} = sys:get_status(Proc),
+ State.
+
+maybe_supervisor_which_children(suspended, Name, Pid) ->
+ error_logger:error_msg("release_handler: a which_children call"
+ " to ~p (~p) was avoided. This supervisor"
+ " is suspended and should likely be upgraded"
+ " differently. Exiting ...~n", [Name, Pid]),
+ error(suspended_supervisor);
+
+maybe_supervisor_which_children(State, Name, Pid) ->
+ case catch supervisor:which_children(Pid) of
+ Res when is_list(Res) ->
+ Res;
+ Other ->
+ error_logger:error_msg("release_handler: ~p~nerror during"
+ " a which_children call to ~p (~p)."
+ " [State: ~p] Exiting ... ~n",
+ [Other, Name, Pid, State]),
+ error(which_children_failed)
+ end.
+
+maybe_get_dynamic_mods(Name, Pid) ->
+ case catch gen:call(Pid, self(), get_modules) of
+ {ok, Res} ->
+ Res;
+ Other ->
+ error_logger:error_msg("release_handler: ~p~nerror during a"
+ " get_modules call to ~p (~p),"
+ " there may be an error in it's"
+ " childspec. Exiting ...~n",
+ [Other, Name, Pid]),
+ error(get_modules_failed)
+ end.
%% XXXX
%% Note: The following is a terrible hack done in order to resolve the
diff --git a/lib/sasl/src/systools_lib.erl b/lib/sasl/src/systools_lib.erl
index f951647b79..1b6ea125d9 100644
--- a/lib/sasl/src/systools_lib.erl
+++ b/lib/sasl/src/systools_lib.erl
@@ -24,7 +24,7 @@
%%
-export([file_term2binary/2, read_term/1, read_term_from_stream/2,
- get_dirs/1, get_path/1]).
+ get_dirs/1, get_path/1, werror/2]).
-include_lib("kernel/include/file.hrl").
@@ -219,6 +219,7 @@ flat([H|T], Ack) ->
flat(T, [H|Ack]);
flat([], Ack) ->
lists:reverse(Ack).
-
-
+
+werror(Options, Warnings) ->
+ lists:member(warnings_as_errors, Options) andalso Warnings =/= [].
diff --git a/lib/sasl/src/systools_make.erl b/lib/sasl/src/systools_make.erl
index 5dc83e7b2a..7f400f5cce 100644
--- a/lib/sasl/src/systools_make.erl
+++ b/lib/sasl/src/systools_make.erl
@@ -44,10 +44,12 @@
%%-----------------------------------------------------------------
%% Create a boot script from a release file.
-%% Options is a list of {path, Path} | silent | local where path sets
-%% the search path, silent supresses error message printing on console,
-%% local generates a script with references to the directories there
-%% the applications are found.
+%% Options is a list of {path, Path} | silent | local
+%% | warnings_as_errors
+%% where path sets the search path, silent supresses error message
+%% printing on console, local generates a script with references
+%% to the directories there the applications are found,
+%% and warnings_as_errors treats warnings as errors.
%%
%% New options: {path,Path} can contain wildcards
%% src_tests
@@ -85,11 +87,16 @@ make_script(RelName, Output, Flags) when is_list(RelName),
ModTestP = {member(src_tests, Flags),xref_p(Flags)},
case get_release(RelName, Path, ModTestP, machine(Flags)) of
{ok, Release, Appls, Warnings} ->
- case generate_script(Output,Release,Appls,Flags) of
- ok ->
+ case systools_lib:werror(Flags, Warnings) of
+ true ->
return(ok,Warnings,Flags);
- Error ->
- return(Error,Warnings,Flags)
+ false ->
+ case generate_script(Output,Release,Appls,Flags) of
+ ok ->
+ return(ok,Warnings,Flags);
+ Error ->
+ return(Error,Warnings,Flags)
+ end
end;
Error ->
return(Error,[],Flags)
@@ -130,10 +137,21 @@ get_outdir(Flags) ->
return(ok,Warnings,Flags) ->
case member(silent,Flags) of
true ->
- {ok,?MODULE,Warnings};
+ case systools_lib:werror(Flags, Warnings) of
+ true ->
+ error;
+ false ->
+ {ok,?MODULE,Warnings}
+ end;
_ ->
- io:format("~s",[format_warning(Warnings)]),
- ok
+ case member(warnings_as_errors,Flags) of
+ true ->
+ io:format("~s",[format_warning(Warnings, true)]),
+ error;
+ false ->
+ io:format("~s",[format_warning(Warnings)]),
+ ok
+ end
end;
return({error,Mod,Error},_,Flags) ->
case member(silent,Flags) of
@@ -1833,78 +1851,89 @@ get_flag(_,_) -> false.
%% Check Options for make_script
check_args_script(Args) ->
cas(Args,
- {undef, undef, undef, undef, undef, undef, undef, undef, []}).
+ {undef, undef, undef, undef, undef, undef, undef, undef,
+ undef, []}).
-cas([], {_Path,_Sil,_Loc,_Test,_Var,_Mach,_Xref,_XrefApps, X}) ->
+cas([], {_Path,_Sil,_Loc,_Test,_Var,_Mach,_Xref,_XrefApps,_Werror, X}) ->
X;
%%% path ---------------------------------------------------------------
-cas([{path, P} | Args], {Path, Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X}) when is_list(P) ->
+cas([{path, P} | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) when is_list(P) ->
case check_path(P) of
ok ->
- cas(Args, {P, Sil, Loc, Test, Var, Mach, Xref, XrefApps,X});
+ cas(Args, {P, Sil, Loc, Test, Var, Mach, Xref, XrefApps,
+ Werror, X});
error ->
cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps,
- X++[{path,P}]})
+ Werror, X++[{path,P}]})
end;
%%% silent -------------------------------------------------------------
-cas([silent | Args], {Path, _Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X}) ->
- cas(Args, {Path, silent, Loc, Test, Var, Mach, Xref, XrefApps, X});
+cas([silent | Args], {Path, _Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) ->
+ cas(Args, {Path, silent, Loc, Test, Var, Mach, Xref, XrefApps,
+ Werror, X});
%%% local --------------------------------------------------------------
-cas([local | Args], {Path, Sil, _Loc, Test, Var, Mach,
- Xref, XrefApps, X}) ->
- cas(Args, {Path, Sil, local, Test, Var, Mach, Xref, XrefApps, X});
+cas([local | Args], {Path, Sil, _Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) ->
+ cas(Args, {Path, Sil, local, Test, Var, Mach, Xref, XrefApps,
+ Werror, X});
%%% src_tests -------------------------------------------------------
-cas([src_tests | Args], {Path, Sil, Loc, _Test, Var, Mach,
- Xref, XrefApps, X}) ->
+cas([src_tests | Args], {Path, Sil, Loc, _Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) ->
cas(Args,
- {Path, Sil, Loc, src_tests, Var, Mach, Xref, XrefApps,X});
+ {Path, Sil, Loc, src_tests, Var, Mach, Xref, Werror, XrefApps,X});
%%% variables ----------------------------------------------------------
-cas([{variables, V} | Args], {Path, Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X}) when is_list(V) ->
+cas([{variables, V} | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) when is_list(V) ->
case check_vars(V) of
ok ->
cas(Args,
- {Path, Sil, Loc, Test, V, Mach, Xref, XrefApps, X});
+ {Path, Sil, Loc, Test, V, Mach, Xref, XrefApps, Werror, X});
error ->
cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps,
- X++[{variables, V}]})
+ Werror, X++[{variables, V}]})
end;
%%% machine ------------------------------------------------------------
-cas([{machine, M} | Args], {Path, Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X}) when is_atom(M) ->
- cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, X});
+cas([{machine, M} | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) when is_atom(M) ->
+ cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, Werror, X});
%%% exref --------------------------------------------------------------
-cas([exref | Args], {Path, Sil, Loc, Test, Var, Mach,
- _Xref, XrefApps, X}) ->
- cas(Args, {Path, Sil, Loc, Test, Var, Mach, exref, XrefApps, X});
+cas([exref | Args], {Path, Sil, Loc, Test, Var, Mach, _Xref,
+ XrefApps, Werror, X}) ->
+ cas(Args, {Path, Sil, Loc, Test, Var, Mach, exref, XrefApps, Werror, X});
%%% exref Apps ---------------------------------------------------------
-cas([{exref, Apps} | Args], {Path, Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X}) when is_list(Apps) ->
+cas([{exref, Apps} | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) when is_list(Apps) ->
case check_apps(Apps) of
ok ->
cas(Args, {Path, Sil, Loc, Test, Var, Mach,
- Xref, Apps, X});
+ Xref, Apps, Werror, X});
error ->
cas(Args, {Path, Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X++[{exref, Apps}]})
+ Xref, XrefApps, Werror, X++[{exref, Apps}]})
end;
%%% outdir Dir ---------------------------------------------------------
-cas([{outdir, Dir} | Args], {Path, Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X}) when is_list(Dir) ->
- cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, X});
+cas([{outdir, Dir} | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) when is_list(Dir) ->
+ cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, Werror, X});
%%% otp_build (secret, not documented) ---------------------------------
-cas([otp_build | Args], {Path, Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X}) ->
- cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, X});
+cas([otp_build | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) ->
+ cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, Werror, X});
%%% no_module_tests (kept for backwards compatibility, but ignored) ----
-cas([no_module_tests | Args], {Path, Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X}) ->
- cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps,X});
+cas([no_module_tests | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) ->
+ cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, Werror, X});
+%%% warnings_as_errors (kept for backwards compatibility, but ignored) ----
+cas([warnings_as_errors | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, _Werror, X}) ->
+ cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps,
+ warnings_as_errors, X});
%%% ERROR --------------------------------------------------------------
-cas([Y | Args], {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, X}) ->
- cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps,X++[Y]}).
+cas([Y | Args], {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps,
+ Werror, X}) ->
+ cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, Werror,
+ X++[Y]}).
@@ -2030,7 +2059,6 @@ check_apps([H|T]) when is_atom(H) ->
check_apps(_) ->
error.
-
%% Format error
format_error(badly_formatted_release) ->
@@ -2144,21 +2172,31 @@ form_tar_err({add, File, Error}) ->
%% Format warning
format_warning(Warnings) ->
- map(fun({warning,W}) -> form_warn(W) end, Warnings).
-
-form_warn({source_not_found,{Mod,_,App,_,_}}) ->
- io_lib:format("*WARNING* ~p: Source code not found: ~p.erl~n",
- [App,Mod]);
-form_warn({{parse_error, File},{_,_,App,_,_}}) ->
- io_lib:format("*WARNING* ~p: Parse error: ~p~n",
- [App,File]);
-form_warn({obj_out_of_date,{Mod,_,App,_,_}}) ->
- io_lib:format("*WARNING* ~p: Object code (~p) out of date~n",[App,Mod]);
-form_warn({exref_undef, Undef}) ->
- F = fun({M,F,A}) ->
- io_lib:format("*WARNING* Undefined function ~p:~p/~p~n",
- [M,F,A])
+ format_warning(Warnings, false).
+
+format_warning(Warnings, Werror) ->
+ Prefix = case Werror of
+ true ->
+ "";
+ false ->
+ "*WARNING* "
+ end,
+ map(fun({warning,W}) -> form_warn(Prefix, W) end, Warnings).
+
+form_warn(Prefix, {source_not_found,{Mod,_,App,_,_}}) ->
+ io_lib:format("~s~p: Source code not found: ~p.erl~n",
+ [Prefix,App,Mod]);
+form_warn(Prefix, {{parse_error, File},{_,_,App,_,_}}) ->
+ io_lib:format("~s~p: Parse error: ~p~n",
+ [Prefix,App,File]);
+form_warn(Prefix, {obj_out_of_date,{Mod,_,App,_,_}}) ->
+ io_lib:format("~s~p: Object code (~p) out of date~n",
+ [Prefix,App,Mod]);
+form_warn(Prefix, {exref_undef, Undef}) ->
+ F = fun({M,F,A}) ->
+ io_lib:format("~sUndefined function ~p:~p/~p~n",
+ [Prefix,M,F,A])
end,
map(F, Undef);
-form_warn(What) ->
- io_lib:format("*WARNING* ~p~n", [What]).
+form_warn(Prefix, What) ->
+ io_lib:format("~s ~p~n", [Prefix,What]).
diff --git a/lib/sasl/src/systools_relup.erl b/lib/sasl/src/systools_relup.erl
index ec5486226c..6d9e922900 100644
--- a/lib/sasl/src/systools_relup.erl
+++ b/lib/sasl/src/systools_relup.erl
@@ -122,7 +122,7 @@
%% rel_filename() = description() = string()
%% Opts = [opt()]
%% opt() = {path, [path()]} | silent | noexec | restart_emulator
-%% | {outdir, string()}
+%% | {outdir, string()} | warnings_as_errors
%% path() = [string()]
%% Ret = ok | error | {ok, Relup, Module, Warnings} | {error, Module, Error}
%%
@@ -139,8 +139,9 @@
%%
%% The option `path' sets search path, `silent' suppresses printing of
%% error messages to the console, `noexec' inhibits the creation of
-%% the output "relup" file, and restart_emulator ensures that the new
-%% emulator is restarted (as the final step).
+%% the output "relup" file, restart_emulator ensures that the new
+%% emulator is restarted (as the final step), and `warnings_as_errors'
+%% treats warnings as errors.
%% ----------------------------------------------------------------
mk_relup(TopRelFile, BaseUpRelDcs, BaseDnRelDcs) ->
mk_relup(TopRelFile, BaseUpRelDcs, BaseDnRelDcs, []).
@@ -153,14 +154,29 @@ mk_relup(TopRelFile, BaseUpRelDcs, BaseDnRelDcs, Opts) ->
{false, false} ->
case R of
{ok, _Res, _Mod, Ws} ->
- print_warnings(Ws),
- ok;
+ print_warnings(Ws, Opts),
+ case systools_lib:werror(Opts, Ws) of
+ true ->
+ error;
+ false ->
+ ok
+ end;
Other ->
print_error(Other),
error
end;
- _ ->
- R
+ _ ->
+ case R of
+ {ok, _Res, _Mod, Ws} ->
+ case systools_lib:werror(Opts, Ws) of
+ true ->
+ error;
+ false ->
+ R
+ end;
+ R ->
+ R
+ end
end;
BadArg ->
erlang:error({badarg, BadArg})
@@ -195,7 +211,12 @@ do_mk_relup(TopRelFile, BaseUpRelDcs, BaseDnRelDcs, Path, Opts) ->
{Dn, Ws2} = foreach_baserel_dn(TopRel, TopApps, BaseDnRelDcs,
Path, Opts, Ws1),
Relup = {TopRel#release.vsn, Up, Dn},
- write_relup_file(Relup, Opts),
+ case systools_lib:werror(Opts, Ws2) of
+ true ->
+ ok;
+ false ->
+ write_relup_file(Relup, Opts)
+ end,
{ok, Relup, ?MODULE, Ws2};
Other ->
throw(Other)
@@ -527,20 +548,29 @@ format_error(Error) ->
io:format("~p~n", [Error]).
-print_warnings(Ws) when is_list(Ws) ->
- lists:foreach(fun(W) -> print_warning(W) end, Ws);
-print_warnings(W) ->
- print_warning(W).
+print_warnings(Ws, Opts) when is_list(Ws) ->
+ lists:foreach(fun(W) -> print_warning(W, Opts) end, Ws);
+print_warnings(W, Opts) ->
+ print_warning(W, Opts).
-print_warning(W) ->
- S = format_warning(W),
+print_warning(W, Opts) ->
+ Prefix = case lists:member(warnings_as_errors, Opts) of
+ true ->
+ "";
+ false ->
+ "*WARNING* "
+ end,
+ S = format_warning(Prefix, W),
io:format("~s", [S]).
-format_warning({erts_vsn_changed, {Rel1, Rel2}}) ->
- io_lib:format("*WARNING* The ERTS version changed between ~p and ~p~n",
- [Rel1, Rel2]);
-format_warning(What) ->
- io_lib:format("*WARNING* ~p~n",[What]).
+format_warning(W) ->
+ format_warning("*WARNING* ", W).
+
+format_warning(Prefix, {erts_vsn_changed, {Rel1, Rel2}}) ->
+ io_lib:format("~sThe ERTS version changed between ~p and ~p~n",
+ [Prefix, Rel1, Rel2]);
+format_warning(Prefix, What) ->
+ io_lib:format("~s~p~n",[Prefix, What]).
get_reason({error, {open, _, _}}) -> open;
diff --git a/lib/sasl/test/release_handler_SUITE.erl b/lib/sasl/test/release_handler_SUITE.erl
index b44da72d35..af2183bfff 100644
--- a/lib/sasl/test/release_handler_SUITE.erl
+++ b/lib/sasl/test/release_handler_SUITE.erl
@@ -58,7 +58,7 @@ cases() ->
[otp_2740, otp_2760, otp_5761, otp_9402, otp_9417,
otp_9395_check_old_code, otp_9395_check_and_purge,
otp_9395_update_many_mods, otp_9395_rm_many_mods,
- instructions, eval_appup].
+ instructions, eval_appup, supervisor_which_children_timeout].
groups() ->
[{release,[],
@@ -523,6 +523,29 @@ no_cc() ->
%%%-----------------------------------------------------------------
%%-----------------------------------------------------------------
+%% release_handler_1:get_supervised_procs/0 test
+%%-----------------------------------------------------------------
+supervisor_which_children_timeout(Conf) ->
+ PrivDir = priv_dir(Conf),
+ Dir = filename:join(PrivDir,"supervisor_which_children_timeout"),
+ DataDir = ?config(data_dir,Conf),
+ LibDir = filename:join([DataDir,release_handler_timeouts]),
+
+ Rel1 = create_and_install_fake_first_release(Dir,[{dummy,"0.1",LibDir}]),
+
+ {ok, Node} = t_start_node(supervisor_which_children_timeout, Rel1, []),
+ Proc = rpc:call(Node, erlang, whereis, [dummy_sup_2]),
+ ok = rpc:call(Node, sys, suspend, [Proc]),
+ Result = {badrpc, {'EXIT', {suspended_supervisor, _}}} =
+ rpc:call(Node, release_handler_1, get_supervised_procs, []),
+ ?t:format("release_handler_1:get_supervised_procs/0: ~p~n", [Result]),
+
+ ok.
+
+supervisor_which_children_timeout(cleanup, Conf) ->
+ stop_node(node_name(supervisor_which_children_timeout)).
+
+%%-----------------------------------------------------------------
%% Ticket: OTP-2740
%% Slogan: vsn not numeric doesn't work so good in release_handling
%%-----------------------------------------------------------------
diff --git a/lib/sasl/test/release_handler_SUITE_data/Makefile.src b/lib/sasl/test/release_handler_SUITE_data/Makefile.src
index 9b07e7ce0a..edb446413d 100644
--- a/lib/sasl/test/release_handler_SUITE_data/Makefile.src
+++ b/lib/sasl/test/release_handler_SUITE_data/Makefile.src
@@ -64,8 +64,13 @@ C= \
c/b.@EMULATOR@ \
c/c_sup.@EMULATOR@
+SUP= \
+ release_handler_timeouts/dummy-0.1/ebin/dummy_app.@EMULATOR@ \
+ release_handler_timeouts/dummy-0.1/ebin/dummy_server.@EMULATOR@ \
+ release_handler_timeouts/dummy-0.1/ebin/dummy_sup.@EMULATOR@ \
+ release_handler_timeouts/dummy-0.1/ebin/dummy_sup_2.@EMULATOR@
-all: $(P2B) $(LIB) $(APP) $(OTP2740) $(C)
+all: $(P2B) $(LIB) $(APP) $(OTP2740) $(C) $(SUP)
P2B/a-2.0/ebin/a.@EMULATOR@: P2B/a-2.0/src/a.erl
erlc $(EFLAGS) -oP2B/a-2.0/ebin P2B/a-2.0/src/a.erl
@@ -195,3 +200,12 @@ c/b.@EMULATOR@: c/b.erl
erlc $(EFLAGS) -oc c/b.erl
c/c_sup.@EMULATOR@: c/c_sup.erl
erlc $(EFLAGS) -oc c/c_sup.erl
+
+release_handler_timeouts/dummy-0.1/ebin/dummy_app.@EMULATOR@: release_handler_timeouts/dummy-0.1/src/dummy_app.erl
+ erlc $(EFLAGS) -orelease_handler_timeouts/dummy-0.1/ebin release_handler_timeouts/dummy-0.1/src/dummy_app.erl
+release_handler_timeouts/dummy-0.1/ebin/dummy_server.@EMULATOR@: release_handler_timeouts/dummy-0.1/src/dummy_server.erl
+ erlc $(EFLAGS) -orelease_handler_timeouts/dummy-0.1/ebin release_handler_timeouts/dummy-0.1/src/dummy_server.erl
+release_handler_timeouts/dummy-0.1/ebin/dummy_sup.@EMULATOR@: release_handler_timeouts/dummy-0.1/src/dummy_sup.erl
+ erlc $(EFLAGS) -orelease_handler_timeouts/dummy-0.1/ebin release_handler_timeouts/dummy-0.1/src/dummy_sup.erl
+release_handler_timeouts/dummy-0.1/ebin/dummy_sup_2.@EMULATOR@: release_handler_timeouts/dummy-0.1/src/dummy_sup_2.erl
+ erlc $(EFLAGS) -orelease_handler_timeouts/dummy-0.1/ebin release_handler_timeouts/dummy-0.1/src/dummy_sup_2.erl
diff --git a/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/ebin/dummy.app b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/ebin/dummy.app
new file mode 100644
index 0000000000..9efdc2e5da
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/ebin/dummy.app
@@ -0,0 +1,7 @@
+{application,dummy,
+ [{description,"a dummy app"},
+ {vsn,"0.1"},
+ {registered,[dummy_app]},
+ {mod,{dummy_app,[]}},
+ {applications,[kernel,stdlib,sasl]},
+ {modules,[dummy_app,dummy_server,dummy_sup,dummy_sup_2]}]}. \ No newline at end of file
diff --git a/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_app.erl b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_app.erl
new file mode 100644
index 0000000000..51363b3630
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_app.erl
@@ -0,0 +1,9 @@
+-module(dummy_app).
+-behaviour(application).
+
+-export([start/2, stop/1]).
+
+start(_,_) ->
+ dummy_sup:start_link().
+
+stop(_) -> ok.
diff --git a/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_server.erl b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_server.erl
new file mode 100644
index 0000000000..382251eba7
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_server.erl
@@ -0,0 +1,56 @@
+-module(dummy_server).
+-behaviour(gen_server).
+
+-export([start_link/0, set_state/1, get_state/0]).
+
+-export([init/1,
+ handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ terminate/2,
+ code_change/3]).
+
+%%
+
+start_link() ->
+ gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
+
+set_state(What) ->
+ gen_server:call(?MODULE, {set_state, What}).
+
+get_state() ->
+ gen_server:call(?MODULE, get_state).
+
+
+%%
+
+init([]) ->
+ say("init, setting state to 0", []),
+ {ok, 0}.
+
+
+handle_call({set_state, NewState}, _From, _State) ->
+ {reply, {ok, NewState}, NewState};
+
+handle_call(get_state, _From, State) ->
+ {reply, State, State}.
+
+handle_cast('__not_implemented', State) ->
+ {noreply, State}.
+
+handle_info(_Info, State) ->
+ say("info ~p, ~p.", [_Info, State]),
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ say("terminate ~p, ~p", [_Reason, _State]),
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ say("code_change ~p, ~p, ~p", [_OldVsn, State, _Extra]),
+ {ok, State}.
+
+%% Internal
+
+say(Format, Data) ->
+ io:format("~p:~p: ~s~n", [?MODULE, self(), io_lib:format(Format, Data)]).
diff --git a/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_sup.erl b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_sup.erl
new file mode 100644
index 0000000000..3d7b5060df
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_sup.erl
@@ -0,0 +1,15 @@
+-module(dummy_sup).
+-behaviour(supervisor).
+
+-export([start_link/0]).
+-export([init/1]).
+
+start_link() ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+init([]) ->
+ DummySup2 = {dummy_sup_2,
+ {dummy_sup_2, start_link, []},
+ permanent, 5000, supervisor, [dummy_sup_2]},
+
+ {ok, {{one_for_one, 10, 10}, [DummySup2]}}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_sup_2.erl b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_sup_2.erl
new file mode 100644
index 0000000000..d936cbcbd6
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_sup_2.erl
@@ -0,0 +1,15 @@
+-module(dummy_sup_2).
+-behaviour(supervisor).
+
+-export([start_link/0]).
+-export([init/1]).
+
+start_link() ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+init([]) ->
+ Dummy = {dummy_server,
+ {dummy_server, start_link, []},
+ permanent, 5000, worker, [dummy_server]},
+
+ {ok, {{one_for_one, 10, 10}, [Dummy]}}.
diff --git a/lib/sasl/test/systools_SUITE.erl b/lib/sasl/test/systools_SUITE.erl
index 539f6de99d..e352247d44 100644
--- a/lib/sasl/test/systools_SUITE.erl
+++ b/lib/sasl/test/systools_SUITE.erl
@@ -396,6 +396,7 @@ src_tests_script(Config) when is_list(Config) ->
?line PSAVE = code:get_path(), % Save path
?line {LatestDir, LatestName} = create_script(latest,Config),
+ ?line BootFile = LatestName ++ ".boot",
?line DataDir = filename:absname(?copydir),
?line LibDir = fname([DataDir, d_missing_src, lib]),
@@ -416,14 +417,32 @@ src_tests_script(Config) when is_list(Config) ->
?line Erl2 = filename:join([P1,"..","src","db2.erl"]),
?line file:delete(Erl2),
- %% Then make script - two warnings should be issued when
- %% src_tests is given
+ %% Then make script
+
+ %% .boot file should not exist
+ ?line ok = file:delete(BootFile),
+ ?line false = filelib:is_regular(BootFile),
+ %% With warnings_as_errors and src_tests option, an error should be issued
+ ?line error =
+ systools:make_script(LatestName, [silent, {path, N}, src_tests,
+ warnings_as_errors]),
+ ?line error =
+ systools:make_script(LatestName, [{path, N}, src_tests,
+ warnings_as_errors]),
+
+ %% due to warnings_as_errors .boot file should still not exist
+ ?line false = filelib:is_regular(BootFile),
+
+ %% Two warnings should be issued when src_tests is given
%% 1. old object code for db1.beam
%% 2. missing source code for db2.beam
?line {ok, _, [{warning,{obj_out_of_date,_}},
{warning,{source_not_found,_}}]} =
systools:make_script(LatestName, [silent, {path, N}, src_tests]),
+ %% .boot file should exist now
+ ?line true = filelib:is_regular(BootFile),
+
%% Without the src_tests option, no warning should be issued
?line {ok, _, []} =
systools:make_script(LatestName, [silent, {path, N}]),
@@ -1150,6 +1169,21 @@ normal_relup(Config) when is_list(Config) ->
[{path, P}, silent]),
?line ok = check_relup([{db, "2.1"}], [{db, "1.0"}]),
+ %% file should not be written if warnings_as_errors is enabled.
+ %% delete before running tests.
+ ?line ok = file:delete("relup"),
+
+ %% Check that warnings are treated as errors
+ ?line error =
+ systools:make_relup(LatestName, [LatestName2], [LatestName1],
+ [{path, P}, warnings_as_errors]),
+ ?line error =
+ systools:make_relup(LatestName, [LatestName2], [LatestName1],
+ [{path, P}, silent, warnings_as_errors]),
+
+ %% relup file should not exist
+ ?line false = filelib:is_regular("relup"),
+
%% Check that warnings get through
?line ok = systools:make_relup(LatestName, [LatestName2], [LatestName1],
[{path, P}]),
@@ -1159,6 +1193,9 @@ normal_relup(Config) when is_list(Config) ->
[{path, P}, silent]),
?line ok = check_relup([{fe, "3.1"}, {db, "2.1"}], [{db, "1.0"}]),
+ %% relup file should exist now
+ ?line true = filelib:is_regular("relup"),
+
?line ok = file:set_cwd(OldDir),
ok.