aboutsummaryrefslogtreecommitdiffstats
path: root/lib/sasl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sasl')
-rw-r--r--lib/sasl/doc/src/notes.xml29
-rw-r--r--lib/sasl/src/format_lib_supp.erl123
-rw-r--r--lib/sasl/src/misc_supp.erl20
-rw-r--r--lib/sasl/src/rb.erl113
-rw-r--r--lib/sasl/src/rb_format_supp.erl10
-rw-r--r--lib/sasl/src/release_handler.erl20
-rw-r--r--lib/sasl/src/systools_make.erl46
-rw-r--r--lib/sasl/src/systools_rc.erl32
-rw-r--r--lib/sasl/src/systools_relup.erl12
-rw-r--r--lib/sasl/test/release_handler_SUITE.erl103
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/Makefile.src18
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/unicode/u-1.0/ebin/u.app8
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/unicode/u-1.0/src/u.erl50
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/unicode/u-1.0/src/u_sup.erl38
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/ebin/u.app8
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/ebin/u.appup3
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/src/u.erl55
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/src/u_sup.erl38
-rw-r--r--lib/sasl/test/sasl_report_SUITE.erl4
-rw-r--r--lib/sasl/vsn.mk2
20 files changed, 500 insertions, 232 deletions
diff --git a/lib/sasl/doc/src/notes.xml b/lib/sasl/doc/src/notes.xml
index 8684151b3a..bc35939d7e 100644
--- a/lib/sasl/doc/src/notes.xml
+++ b/lib/sasl/doc/src/notes.xml
@@ -31,6 +31,35 @@
</header>
<p>This document describes the changes made to the SASL application.</p>
+<section><title>SASL 3.0.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Documented default values for the 'mod' and
+ 'start_phases' fields in .app files were not allowed as
+ actual values in a .app file. This is now corrected.</p>
+ <p>
+ Own Id: OTP-14029</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Miscellaneous updates due to atoms containing
+ arbitrary Unicode characters. </p>
+ <p>
+ Own Id: OTP-14285</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SASL 3.0.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/sasl/src/format_lib_supp.erl b/lib/sasl/src/format_lib_supp.erl
index 0b474a0232..80dcdc91da 100644
--- a/lib/sasl/src/format_lib_supp.erl
+++ b/lib/sasl/src/format_lib_supp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,15 +25,12 @@
%%% tools.
%%% The main parts are:
%%% 1) print_info. Prints information tagged by 'header', 'data',
-%%% 'table', 'items' and 'newline'.
+%%% 'items' and 'newline'.
%%%---------------------------------------------------------------------
%% intermodule exports
-export([print_info/2, print_info/3]).
-%% exports for use within module
--export([maxcol/2]).
-
%%---------------------------------------------------------------------
%% Format is an ordered list of:
%% {header, HeaderString}
@@ -42,10 +39,6 @@
%% (if possible); 'Key: Value'.
%% Elements in the list may also be single terms, which are
%% printed as they are.
-%% {table, {TableName, ColumnNames, Columns}}
-%% ColumnNames is a tuple of names for the columns, and
-%% Columns is a list, where each element is a tuple of
-%% data for that column.
%% {items, {Name, Items}}
%% Items is a list of KeyValue_tuples. Will be printed as:
%% 'Name:
@@ -77,9 +70,6 @@ print_format(Device, _Line, []) ->
print_format(Device, Line, [{data, Data}|T]) ->
print_data(Device, Line, Data),
print_format(Device, Line, T);
-print_format(Device, Line, [{table, Table}|T]) ->
- _ = print_table(Device, Line, Table),
- print_format(Device, Line, T);
print_format(Device, Line, [{items, Items}|T]) ->
print_items(Device, Line, Items),
print_format(Device, Line, T);
@@ -94,51 +84,49 @@ print_data(Device, Line, [{Key, Value}|T]) ->
print_one_line(Device, Line, Key, Value),
print_data(Device, Line, T);
print_data(Device, Line, [Value|T]) ->
- io:format(Device, "~p~n", [Value]),
+ Modifier = misc_supp:modifier(Device),
+ io:format(Device, "~"++Modifier++"p~n", [Value]),
print_data(Device, Line, T).
+
print_items(Device, Line, {Name, Items}) ->
print_items(Device, Line, Name, Items).
-print_table(Device, Line, {TableName, ColumnNames, Columns}) ->
- print_table(Device, Line, TableName, ColumnNames, Columns).
-
print_newlines(_Device, 0) -> ok;
print_newlines(Device, N) when N > 0 ->
io:format(Device, '~n', []),
print_newlines(Device, N-1).
print_one_line(Device, Line, Key, Value) ->
- StrKey = term_to_string(Key),
+ Modifier = misc_supp:modifier(Device),
+ StrKey = term_to_string(Key,Modifier),
KeyLen = lists:min([length(StrKey), Line]),
ValueLen = Line - KeyLen,
- Format1 = lists:concat(["~-", KeyLen, s]),
- Format2 = lists:concat(["~", ValueLen, "s~n"]),
+ Format1 = lists:concat(["~-", KeyLen, Modifier, "s"]),
+ Format2 = lists:concat(["~", ValueLen, Modifier, "s~n"]),
io:format(Device, Format1, [StrKey]),
- Try = term_to_string(Value),
+ Try = term_to_string(Value,Modifier),
Length = length(Try),
if
Length < ValueLen ->
io:format(Device, Format2, [Try]);
true ->
io:format(Device, "~n ", []),
- Format3 = lists:concat(["~", Line, ".9p~n"]),
+ Format3 = lists:concat(["~", Line, ".9", Modifier, "p~n"]),
io:format(Device, Format3, [Value])
end.
-term_to_string(Value) ->
- lists:flatten(io_lib:format(get_format(Value), [Value])).
+term_to_string(Value,Modifier) ->
+ lists:flatten(io_lib:format(get_format(Value,Modifier), [Value])).
-get_format(Value) ->
- case misc_supp:is_string(Value) of
- true -> "~s";
- false -> "~p"
+get_format([],_) ->
+ "~p";
+get_format(Value,Modifier) ->
+ case io_lib:printable_list(Value) of
+ true -> "~"++Modifier++"s";
+ false -> "~"++Modifier++"p"
end.
-make_list(0, _Elem) -> [];
-make_list(N, Elem) -> [Elem|make_list(N-1, Elem)].
-
-
%%-----------------------------------------------------------------
%% Items
%%-----------------------------------------------------------------
@@ -150,76 +138,3 @@ print_item_elements(_Device, _Line, []) -> ok;
print_item_elements(Device, Line, [{Key, Value}|T]) ->
print_one_line(Device, Line, lists:concat([" ", Key]), Value),
print_item_elements(Device, Line, T).
-
-%%-----------------------------------------------------------------
-%% Table handling
-%%-----------------------------------------------------------------
-extra_space_between_columns() -> 3.
-
-find_max_col([Row | T], ColumnSizes) ->
- find_max_col(T, misc_supp:multi_map({format_lib_supp, maxcol},
- [Row, ColumnSizes]));
-
-find_max_col([], ColumnSizes) -> ColumnSizes.
-
-maxcol(Term, OldMax) ->
- lists:max([length(term_to_string(Term)), OldMax]).
-
-make_column_format(With) ->
- lists:concat(["~", With + extra_space_between_columns(), s]).
-
-is_correct_column_length(_Length, []) -> true;
-is_correct_column_length(Length, [Tuple|T]) ->
- case size(Tuple) of
- Length -> is_correct_column_length(Length, T);
- _ -> false
- end;
-is_correct_column_length(_, _) -> false.
-
-print_table(Device, Line, TableName, _TupleOfColumnNames, []) ->
- print_one_line(Device, Line, TableName, "<empty table>"),
- io:format(Device, "~n", []);
-
-print_table(Device, Line, TableName, TupleOfColumnNames, ListOfTuples)
- when is_list(ListOfTuples), is_tuple(TupleOfColumnNames) ->
- case is_correct_column_length(size(TupleOfColumnNames),
- ListOfTuples) of
- true ->
- print_one_line(Device, Line, TableName, " "),
- ListOfColumnNames = tuple_to_list(TupleOfColumnNames),
- ListOfLists = lists:map(fun(Tuple) ->
- tuple_to_list(Tuple)
- end,
- ListOfTuples),
- ColWidths = find_max_col([ListOfColumnNames |
- ListOfLists],
- make_list(length(ListOfColumnNames),0)),
- Format = lists:flatten([lists:map(fun(CW) ->
- make_column_format(CW)
- end,
- ColWidths), "~n"]),
- io:format(Device, Format, ListOfColumnNames),
- io:format(Device,
- lists:concat(['~', extra_space_between_columns(),
- 'c', '~', lists:sum(ColWidths)
- + (length(ColWidths) - 1)
- * extra_space_between_columns(),
- 'c~n']), [$ , $-]),
- lists:foreach(fun(List) ->
- print_row(List, Device, Format)
- end,
- ListOfLists),
- io:format(Device, '~n', []),
- true;
- false ->
- {error, {'a tuple has wrong size',
- {TableName, TupleOfColumnNames, ListOfTuples}}}
- end.
-
-%%--------------------------------------------------
-%% Device MUST be 2nd arg because of extraarg ni foreach...
-%%--------------------------------------------------
-print_row(Row, Device, Format) ->
- io:format(Device, Format,
- lists:map(fun(Term) -> term_to_string(Term) end,
- Row)).
diff --git a/lib/sasl/src/misc_supp.erl b/lib/sasl/src/misc_supp.erl
index 093b337a2c..cbbcba0def 100644
--- a/lib/sasl/src/misc_supp.erl
+++ b/lib/sasl/src/misc_supp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,7 +32,7 @@
%%%---------------------------------------------------------------------
-export([format_pdict/3, format_tuples/2, assq/2, passq/2, is_string/1,
- multi_map/2]).
+ multi_map/2, modifier/1]).
%%-----------------------------------------------------------------
%% Uses format_tuples to format the data in process dictionary.
@@ -105,3 +105,19 @@ multi_map(Func, ListOfLists) ->
[apply(Func, lists:map(fun(List) -> hd(List) end, ListOfLists)) |
multi_map(Func,
lists:map(fun(List) -> tl(List) end, ListOfLists))].
+
+%%%-----------------------------------------------------------------
+%%% Check encoding of the given device and return "t" if this format
+%%% modifier should be used.
+modifier(Device) ->
+ Encoding =
+ case io:getopts(Device) of
+ List when is_list(List) ->
+ proplists:get_value(encoding,List,latin1);
+ _ ->
+ latin1
+ end,
+ encoding_to_modifier(Encoding).
+
+encoding_to_modifier(latin1) -> "";
+encoding_to_modifier(_) -> "t".
diff --git a/lib/sasl/src/rb.erl b/lib/sasl/src/rb.erl
index 79df150b41..6595d29a9c 100644
--- a/lib/sasl/src/rb.erl
+++ b/lib/sasl/src/rb.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -273,7 +273,7 @@ code_change(_OldVsn, State, _Extra) ->
open_log_file(standard_io) -> standard_io;
open_log_file(Fd) when is_atom(Fd),Fd=/=standard_error ->
case whereis(Fd) of
- undefined -> io:format("rb: Registered name not found '~s'.~n",
+ undefined -> io:format("rb: Registered name not found '~ts'.~n",
[Fd]),
io:format("rb: Using standard_io~n"),
open_log_file(standard_io);
@@ -281,10 +281,10 @@ open_log_file(Fd) when is_atom(Fd),Fd=/=standard_error ->
end;
open_log_file(Fd) when is_pid(Fd)-> Fd;
open_log_file(FileName) when is_list(FileName) ->
- case file:open(FileName, [write,append]) of
+ case file:open(FileName, [write,append,{encoding,utf8}]) of
{ok, Fd} -> Fd;
Error ->
- io:format("rb: Cannot open file '~s' (~w).~n",
+ io:format("rb: Cannot open file '~ts' (~w).~n",
[FileName, Error]),
io:format("rb: Using standard_io~n"),
standard_io
@@ -419,8 +419,8 @@ read_reports(No, Fd, Fname, Max, Type) ->
add_report_data(NewRes, No, Fname);
{error, [Problem | Res]} ->
_ = file:close(Fd),
- io:format("Error: ~p~n",[Problem]),
- io:format("Salvaged ~p entries from corrupt report file ~s...~n",
+ io:format("Error: ~tp~n",[Problem]),
+ io:format("Salvaged ~p entries from corrupt report file ~ts...~n",
[length(Res),Fname]),
NewRes =
if
@@ -431,7 +431,7 @@ read_reports(No, Fd, Fname, Max, Type) ->
end,
add_report_data(NewRes, No, Fname);
Else ->
- io:format("err ~p~n", [Else]),
+ io:format("err ~tp~n", [Else]),
[{No, unknown, "Can't read reports from file " ++ Fname,
"???", Fname, 0}]
end.
@@ -530,21 +530,18 @@ get_short_descr({{Date, Time}, {error_report, Pid, {_, crash_report, Rep}}}) ->
{value, {_Key, N}} -> N;
_ -> Pid
end,
- NameStr = lists:flatten(io_lib:format("~w", [Name])),
- {NameStr, date_str(Date, Time)};
+ {Name, date_str(Date, Time)};
get_short_descr({{Date, Time}, {error_report, Pid, {_, supervisor_report,Rep}}}) ->
Name =
case lists:keysearch(supervisor, 1, Rep) of
{value, {_Key, N}} when is_atom(N) -> N;
_ -> Pid
end,
- NameStr = lists:flatten(io_lib:format("~w", [Name])),
- {NameStr, date_str(Date,Time)};
+ {Name, date_str(Date,Time)};
get_short_descr({{Date, Time}, {_Type, Pid, _}}) ->
- NameStr = lists:flatten(io_lib:format("~w", [Pid])),
- {NameStr, date_str(Date,Time)};
+ {Pid, date_str(Date,Time)};
get_short_descr(_) ->
- {"???", "???"}.
+ {'???', "???"}.
date_str({Y,Mo,D}=Date,{H,Mi,S}=Time) ->
case application:get_env(sasl,utc_log) of
@@ -571,53 +568,57 @@ local_time_to_universal_time({Date,Time}) ->
end.
-print_list(Fd, Data, Type) ->
+print_list(Fd, Data0, Type) ->
+ Modifier = misc_supp:modifier(Fd),
Header = {"No", "Type", "Process", "Date Time"},
- Width = find_width([Header | Data], 0)+1,
- DateWidth = find_date_width([Header | Data], 0) +1,
- Format = lists:concat(["~4s~20s ~", Width, "s~20s~n"]),
+ {DescrWidth,DateWidth,Data} = find_widths(Data0, Modifier, 7, 13, []),
+ Format = lists:concat(["~4s~20s ~", DescrWidth, "s~20s~n"]),
io:format(Fd, Format, tuple_to_list(Header)),
io:format(Fd, Format, ["==", "====", "=======", "==== ===="]),
- print_list(Fd, Data, Type, Width, DateWidth).
-print_list(_, [], _, _, _) -> true;
-print_list(Fd, [H|T], Type, Width, DateWidth) ->
- print_one_report(Fd, H, Type, Width, DateWidth),
- print_list(Fd, T, Type, Width, DateWidth).
-
-find_width([], Width) -> Width;
-find_width([H|T], Width) ->
- Try = length(element(3, H)),
- if
- Try > Width -> find_width(T, Try);
- true -> find_width(T, Width)
- end.
-find_date_width([], Width) -> Width;
-find_date_width([H|T], Width) ->
- Try = length(element(4, H)),
- if
- Try > Width -> find_date_width(T, Try);
- true -> find_date_width(T, Width)
- end.
+ print_list(Fd, Data, Type, DescrWidth, DateWidth, Modifier).
+print_list(_, [], _, _, _, _) -> true;
+print_list(Fd, [H|T], Type, Width, DateWidth, Modifier) ->
+ print_one_report(Fd, H, Type, Width, DateWidth, Modifier),
+ print_list(Fd, T, Type, Width, DateWidth, Modifier).
+
+
+find_widths([], _Modifier, DescrWidth, DateWidth, Data) ->
+ {DescrWidth+1, DateWidth+1, lists:reverse(Data)};
+find_widths([H|T], Modifier, DescrWidth, DateWidth, Data) ->
+ DescrTerm = element(3,H),
+ Descr = lists:flatten(io_lib:format("~"++Modifier++"w", [DescrTerm])),
+ DescrTry = length(Descr),
+ NewDescrWidth =
+ if
+ DescrTry > DescrWidth -> DescrTry;
+ true -> DescrWidth
+ end,
+ DateTry = length(element(4, H)),
+ NewDateWitdh =
+ if
+ DateTry > DateWidth -> DateTry;
+ true -> DateWidth
+ end,
+ NewH = setelement(3,H,Descr),
+ find_widths(T, Modifier, NewDescrWidth, NewDateWitdh, [NewH|Data]).
print_one_report(Fd, {No, RealType, ShortDescr, Date, _Fname, _FilePos},
WantedType,
- Width, DateWidth) ->
+ Width, DateWidth, Modifier) ->
if
WantedType == all ->
print_short_descr(Fd, No, RealType, ShortDescr, Date, Width,
- DateWidth);
+ DateWidth, Modifier);
WantedType == RealType ->
print_short_descr(Fd, No, RealType, ShortDescr, Date, Width,
- DateWidth);
+ DateWidth, Modifier);
true -> ok
end.
-print_short_descr(Fd, No, Type, ShortDescr, Date, Width, DateWidth) ->
- Format = lists:concat(["~4w~20w ~", Width, "s~", DateWidth,"s~n"]),
- io:format(Fd, Format, [No,
- Type,
- io_lib:format("~s", [ShortDescr]),
- Date]).
+print_short_descr(Fd, No, Type, ShortDescr, Date, Width, DateWidth, Modifier) ->
+ Format = lists:concat(["~4w~20", Modifier, "w ~", Width, Modifier, "s~",
+ DateWidth, "s~n"]),
+ io:format(Fd, Format, [No, Type, ShortDescr, Date]).
print_report_by_num(Dir, Data, Number, Device, Abort, Log) ->
{_,Device1} = print_report(Dir, Data, Number, Device, Abort, Log),
@@ -658,7 +659,7 @@ print_report(Dir, Data, Number, Device, Abort, Log) ->
{ok, Fd} ->
read_rep(Fd, FilePosition, Device, Abort, Log);
_ ->
- io:format("rb: can't open file ~p~n", [Fname]),
+ io:format("rb: can't open file ~tp~n", [Fname]),
{proceed,Device}
end;
no_report ->
@@ -691,14 +692,14 @@ print_grep_report(Dir, Data, Number, Device, RegExp, Abort, Log) ->
{ok, Fd} when is_pid(Fd) ->
check_rep(Fd, FilePosition, Device, RegExp, Number, Abort, Log);
_ ->
- io:format("rb: can't open file ~p~n", [Fname]),
+ io:format("rb: can't open file ~tp~n", [Fname]),
{proceed,Device}
end.
check_rep(Fd, FilePosition, Device, RegExp, Number, Abort, Log) ->
case read_rep_msg(Fd, FilePosition) of
{Date, Msg} ->
- MsgStr = lists:flatten(io_lib:format("~p",[Msg])),
+ MsgStr = lists:flatten(io_lib:format("~tp",[Msg])),
case run_re(MsgStr, RegExp) of
match ->
io:format("Found match in report number ~w~n", [Number]),
@@ -722,7 +723,7 @@ run_re(Subject, Regexp) ->
run_re(Subject, Regexp, []).
run_re(Subject, Regexp, Options) ->
- case re:run(Subject, Regexp, Options) of
+ case re:run(Subject, Regexp, [unicode|Options--[unicode]]) of
nomatch ->
nomatch;
_ ->
@@ -748,7 +749,7 @@ filter_report(Dir, Data, Filters, Number, Device, Abort, Log) ->
{ok, Fd} ->
filter_rep(Filters, Fd, FilePosition, Device, Abort, Log);
_ ->
- io:format("rb: can't open file ~p~n", [Fname]),
+ io:format("rb: can't open file ~tp~n", [Fname]),
{proceed,Device}
end;
no_report ->
@@ -800,7 +801,7 @@ filter_report([{Key, RegExp, re}|T], Msg) ->
undefined ->
false;
Value ->
- Subject = lists:flatten(io_lib:format("~p",[Value])),
+ Subject = lists:flatten(io_lib:format("~tp",[Value])),
case run_re(Subject, RegExp) of
match ->
filter_report(T, Msg);
@@ -812,7 +813,7 @@ filter_report([{Key, RegExp, re, no}|T], Msg) ->
undefined ->
true;
Value ->
- Subject = lists:flatten(io_lib:format("~p",[Value])),
+ Subject = lists:flatten(io_lib:format("~tp",[Value])),
case run_re(Subject, RegExp) of
match -> false;
_ -> filter_report(T, Msg)
@@ -890,7 +891,7 @@ read_rep(Fd, FilePosition, Device, Abort, Log) ->
handle_bad_form(Date, Msg, Device, Abort, Log) ->
io:format("rb: ERROR! A report on bad form was encountered. " ++
"It can not be printed to the log.~n~n"),
- io:format("Details:~n~p ~p~n~n", [Date,Msg]),
+ io:format("Details:~n~p ~tp~n~n", [Date,Msg]),
case {Abort,Device,open_log_file(Log)} of
{true,standard_io,standard_io} ->
io:format("rb: Logging aborted.~n"),
@@ -899,7 +900,7 @@ handle_bad_form(Date, Msg, Device, Abort, Log) ->
io:format("rb: Logging resumed...~n~n"),
{proceed,Device};
{_,_,standard_io} ->
- io:format("rb: Can not reopen ~p. Logging aborted.~n", [Log]),
+ io:format("rb: Can not reopen ~tp. Logging aborted.~n", [Log]),
{abort,Device};
{true,_,NewDevice} ->
io:format(NewDevice,
diff --git a/lib/sasl/src/rb_format_supp.erl b/lib/sasl/src/rb_format_supp.erl
index 0004d85af4..1eda43dae4 100644
--- a/lib/sasl/src/rb_format_supp.erl
+++ b/lib/sasl/src/rb_format_supp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -94,13 +94,15 @@ print(Date, Report, Device) ->
[{header, Header}]),
io:format(Device, Format, Args);
{Type, _GL, TypeReport} ->
- io:format(Device, "~nInfo type <~w> ~s~n",
+ Modifier = misc_supp:modifier(Device),
+ io:format(Device, "~nInfo type <~"++Modifier++"w> ~s~n",
[Type, Date]),
- io:format(Device, "~p", [TypeReport]);
+ io:format(Device, "~"++Modifier++"p", [TypeReport]);
_ ->
+ Modifier = misc_supp:modifier(Device),
io:format("~nPrinting info of unknown type... ~s~n",
[Date]),
- io:format(Device, "~p", [Report])
+ io:format(Device, "~"++Modifier++"p", [Report])
% end
end.
diff --git a/lib/sasl/src/release_handler.erl b/lib/sasl/src/release_handler.erl
index 669ffd95c0..d0a7c7332d 100644
--- a/lib/sasl/src/release_handler.erl
+++ b/lib/sasl/src/release_handler.erl
@@ -640,8 +640,8 @@ handle_call({install_release, Vsn, ErrorAction, Opts}, From, S) ->
{noreply, NS};
{'EXIT', Reason} ->
io:format("release_handler:"
- "install_release(Vsn=~p Opts=~p) failed, "
- "Reason=~p~n", [Vsn, Opts, Reason]),
+ "install_release(Vsn=~tp Opts=~tp) failed, "
+ "Reason=~tp~n", [Vsn, Opts, Reason]),
gen_server:reply(From, {error, Reason}),
case ErrorAction of
restart ->
@@ -1124,7 +1124,7 @@ new_emulator_make_hybrid_config(CurrentVsn,ToVsn,TmpVsn,RelDir,Masters) ->
{ok,[FC]} ->
FC;
{error,Error1} ->
- io:format("Warning: ~w can not read ~p: ~p~n",
+ io:format("Warning: ~w can not read ~tp: ~tp~n",
[?MODULE,FromFile,Error1]),
[]
end,
@@ -1134,7 +1134,7 @@ new_emulator_make_hybrid_config(CurrentVsn,ToVsn,TmpVsn,RelDir,Masters) ->
{ok,[ToConfig]} ->
[lists:keyfind(App,1,ToConfig) || App <- [kernel,stdlib,sasl]];
{error,Error2} ->
- io:format("Warning: ~w can not read ~p: ~p~n",
+ io:format("Warning: ~w can not read ~tp: ~tp~n",
[?MODULE,ToFile,Error2]),
[false,false,false]
end,
@@ -1143,8 +1143,9 @@ new_emulator_make_hybrid_config(CurrentVsn,ToVsn,TmpVsn,RelDir,Masters) ->
Config2 = replace_config(stdlib,Config1,Stdlib),
Config3 = replace_config(sasl,Config2,Sasl),
- ConfigStr = io_lib:format("~p.~n",[Config3]),
- write_file(TmpFile,ConfigStr,Masters).
+ ConfigStr = io_lib:format("%% ~s~n~tp.~n",
+ [epp:encoding_to_string(utf8),Config3]),
+ write_file(TmpFile,unicode:characters_to_binary(ConfigStr),Masters).
%% Take the configuration for application App from the new config and
%% insert in the old config.
@@ -1807,7 +1808,7 @@ check_opt_file(FileName, Type, Masters) ->
ok ->
true;
_Error ->
- io:format("Warning: ~p missing (optional)~n", [FileName]),
+ io:format("Warning: ~tp missing (optional)~n", [FileName]),
false
end.
@@ -1874,9 +1875,10 @@ write_releases_1(Dir, NewReleases, Masters) ->
write_releases_m(Dir, NewReleases, Masters).
do_write_release(Dir, RELEASES, NewReleases) ->
- case file:open(filename:join(Dir, RELEASES), [write]) of
+ case file:open(filename:join(Dir, RELEASES), [write,{encoding,utf8}]) of
{ok, Fd} ->
- ok = io:format(Fd, "~p.~n", [NewReleases]),
+ ok = io:format(Fd, "%% ~s~n~tp.~n",
+ [epp:encoding_to_string(utf8),NewReleases]),
ok = file:close(Fd);
{error, Reason} ->
{error, Reason}
diff --git a/lib/sasl/src/systools_make.erl b/lib/sasl/src/systools_make.erl
index 654a0acff2..391b1fb5cc 100644
--- a/lib/sasl/src/systools_make.erl
+++ b/lib/sasl/src/systools_make.erl
@@ -1152,10 +1152,10 @@ generate_script(Output, Release, Appls, Flags) ->
},
ScriptFile = Output ++ ".script",
- case file:open(ScriptFile, [write]) of
+ case file:open(ScriptFile, [write,{encoding,utf8}]) of
{ok, Fd} ->
- io:format(Fd, "%% script generated at ~w ~w\n~p.\n",
- [date(), time(), Script]),
+ io:format(Fd, "%% ~s\n%% script generated at ~w ~w\n~tp.\n",
+ [epp:encoding_to_string(utf8), date(), time(), Script]),
case file:close(Fd) of
ok ->
BootFile = Output ++ ".boot",
@@ -2234,9 +2234,9 @@ check_apps(_) ->
format_error(badly_formatted_release) ->
io_lib:format("Syntax error in the release file~n",[]);
format_error({illegal_name, Name}) ->
- io_lib:format("Illegal name (~p) in the release file~n",[Name]);
+ io_lib:format("Illegal name (~tp) in the release file~n",[Name]);
format_error({illegal_form, Form}) ->
- io_lib:format("Illegal tag in the release file: ~p~n",[Form]);
+ io_lib:format("Illegal tag in the release file: ~tp~n",[Form]);
format_error({missing_parameter,Par}) ->
io_lib:format("Missing parameter (~p) in the release file~n",[Par]);
format_error({illegal_applications,Names}) ->
@@ -2251,7 +2251,7 @@ format_error({mandatory_app,Name,Type}) ->
format_error({duplicate_register,Dups}) ->
io_lib:format("Duplicated register names: ~n~ts",
[map(fun({{Reg,App1,_,_},{Reg,App2,_,_}}) ->
- io_lib:format("\t~w registered in ~w and ~w~n",
+ io_lib:format("\t~tw registered in ~w and ~w~n",
[Reg,App1,App2])
end, Dups)]);
format_error({undefined_applications,Apps}) ->
@@ -2275,20 +2275,20 @@ format_error({modules,ModErrs}) ->
format_error({circular_dependencies,Apps}) ->
io_lib:format("Circular dependencies among applications: ~p~n",[Apps]);
format_error({not_found,File}) ->
- io_lib:format("File not found: ~p~n",[File]);
+ io_lib:format("File not found: ~tp~n",[File]);
format_error({parse,File,{Line,Mod,What}}) ->
Str = Mod:format_error(What),
io_lib:format("~ts:~w: ~ts\n",[File, Line, Str]);
format_error({read,File}) ->
- io_lib:format("Cannot read ~p~n",[File]);
+ io_lib:format("Cannot read ~tp~n",[File]);
format_error({open,File,Error}) ->
- io_lib:format("Cannot open ~p - ~ts~n",
+ io_lib:format("Cannot open ~tp - ~ts~n",
[File,file:format_error(Error)]);
format_error({close,File,Error}) ->
- io_lib:format("Cannot close ~p - ~ts~n",
+ io_lib:format("Cannot close ~tp - ~ts~n",
[File,file:format_error(Error)]);
format_error({delete,File,Error}) ->
- io_lib:format("Cannot delete ~p - ~ts~n",
+ io_lib:format("Cannot delete ~tp - ~ts~n",
[File,file:format_error(Error)]);
format_error({tar_error,What}) ->
form_tar_err(What);
@@ -2297,7 +2297,7 @@ format_error({warnings_treated_as_errors,Warnings}) ->
[map(fun(W) -> form_warn("",W) end, Warnings)]);
format_error(ListOfErrors) when is_list(ListOfErrors) ->
format_errors(ListOfErrors);
-format_error(E) -> io_lib:format("~p~n",[E]).
+format_error(E) -> io_lib:format("~tp~n",[E]).
format_errors(ListOfErrors) ->
map(fun({error,E}) -> form_err(E);
@@ -2313,19 +2313,19 @@ form_err({module_not_found,App,Mod}) ->
form_err({error_add_appl, {Name, {tar_error, What}}}) ->
io_lib:format("~p: ~ts~n",[Name,form_tar_err(What)]);
form_err(E) ->
- io_lib:format("~p~n",[E]).
+ io_lib:format("~tp~n",[E]).
form_reading({not_found,File}) ->
- io_lib:format("File not found: ~p~n",[File]);
+ io_lib:format("File not found: ~tp~n",[File]);
form_reading({application_vsn, {Name,Vsn}}) ->
- io_lib:format("Application ~ts with version ~p not found~n",[Name, Vsn]);
+ io_lib:format("Application ~ts with version ~tp not found~n",[Name, Vsn]);
form_reading({parse,File,{Line,Mod,What}}) ->
Str = Mod:format_error(What),
io_lib:format("~ts:~w: ~ts\n",[File, Line, Str]);
form_reading({read,File}) ->
- io_lib:format("Cannot read ~p~n",[File]);
+ io_lib:format("Cannot read ~tp~n",[File]);
form_reading({{bad_param, P},_}) ->
- io_lib:format("Bad parameter in .app file: ~p~n",[P]);
+ io_lib:format("Bad parameter in .app file: ~tp~n",[P]);
form_reading({{missing_param,P},_}) ->
io_lib:format("Missing parameter in .app file: ~p~n",[P]);
form_reading({badly_formatted_application,_}) ->
@@ -2334,12 +2334,12 @@ form_reading({override_include,Apps}) ->
io_lib:format("Tried to include not (in .app file) specified applications: ~p~n",
[Apps]);
form_reading({no_valid_version, {{_, SVsn}, {_, File, FVsn}}}) ->
- io_lib:format("No valid version (~p) of .app file found. Found file ~p with version ~p~n",
+ io_lib:format("No valid version (~tp) of .app file found. Found file ~tp with version ~tp~n",
[SVsn, File, FVsn]);
form_reading({parse_error, {File, Line, Error}}) ->
- io_lib:format("Parse error in file: ~p. Line: ~w Error: ~p; ~n", [File, Line, Error]);
+ io_lib:format("Parse error in file: ~tp. Line: ~w Error: ~tp; ~n", [File, Line, Error]);
form_reading(W) ->
- io_lib:format("~p~n",[W]).
+ io_lib:format("~tp~n",[W]).
form_tar_err({open, File, Error}) ->
io_lib:format("Cannot open tar file ~ts - ~ts~n",
@@ -2357,14 +2357,14 @@ form_warn(Prefix, {source_not_found,{Mod,App,_}}) ->
io_lib:format("~ts~w: Source code not found: ~w.erl~n",
[Prefix,App,Mod]);
form_warn(Prefix, {{parse_error, File},{_,_,App,_,_}}) ->
- io_lib:format("~ts~w: Parse error: ~p~n",
+ io_lib:format("~ts~w: Parse error: ~tp~n",
[Prefix,App,File]);
form_warn(Prefix, {obj_out_of_date,{Mod,App,_}}) ->
io_lib:format("~ts~w: Object code (~w) out of date~n",
[Prefix,App,Mod]);
form_warn(Prefix, {exref_undef, Undef}) ->
F = fun({M,F,A}) ->
- io_lib:format("~tsUndefined function ~w:~w/~w~n",
+ io_lib:format("~tsUndefined function ~w:~tw/~w~n",
[Prefix,M,F,A])
end,
map(F, Undef);
@@ -2373,4 +2373,4 @@ form_warn(Prefix, missing_sasl) ->
"Can not upgrade with this release~n",
[Prefix]);
form_warn(Prefix, What) ->
- io_lib:format("~ts~p~n", [Prefix,What]).
+ io_lib:format("~ts~tp~n", [Prefix,What]).
diff --git a/lib/sasl/src/systools_rc.erl b/lib/sasl/src/systools_rc.erl
index 7722cef57b..c570ed00ab 100644
--- a/lib/sasl/src/systools_rc.erl
+++ b/lib/sasl/src/systools_rc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -942,41 +942,41 @@ format_error(too_many_point_of_no_return) ->
io_lib:format("Too many point_of_no_return~n", []);
format_error({bad_instruction, X}) ->
- io_lib:format("Bad instruction: ~p~n", [X]);
+ io_lib:format("Bad instruction: ~tp~n", [X]);
format_error({bad_module, X}) ->
- io_lib:format("Bad module: ~p(should be atom())~n", [X]);
+ io_lib:format("Bad module: ~tp(should be atom())~n", [X]);
format_error({bad_code_change, X}) ->
- io_lib:format("Bad code_change: ~p(should be {Mod, Extra})~n", [X]);
+ io_lib:format("Bad code_change: ~tp(should be {Mod, Extra})~n", [X]);
format_error({bad_change, X}) ->
- io_lib:format("Bad change spec: ~p(should be soft | {advanced, E})~n", [X]);
+ io_lib:format("Bad change spec: ~tp(should be soft | {advanced, E})~n", [X]);
format_error({bad_mod_type, X}) ->
- io_lib:format("Bad module type: ~p(should be static | dynamic)~n", [X]);
+ io_lib:format("Bad module type: ~tp(should be static | dynamic)~n", [X]);
format_error({bad_purge_method, X}) ->
- io_lib:format("Bad purge method: ~p(should be soft_purge | brutal_purge)~n",
+ io_lib:format("Bad purge method: ~tp(should be soft_purge | brutal_purge)~n",
[X]);
format_error({bad_list, X}) ->
- io_lib:format("Bad list: ~p~n", [X]);
+ io_lib:format("Bad list: ~tp~n", [X]);
format_error({bad_args_list, X}) ->
- io_lib:format("Bad argument list: ~p~n", [X]);
+ io_lib:format("Bad argument list: ~tp~n", [X]);
format_error({bad_node, X}) ->
- io_lib:format("Bad node: ~p(should be atom())~n", [X]);
+ io_lib:format("Bad node: ~tp(should be atom())~n", [X]);
format_error({bad_application, X}) ->
- io_lib:format("Bad application: ~p(should be atom())~n", [X]);
+ io_lib:format("Bad application: ~tp(should be atom())~n", [X]);
format_error({bad_func, X}) ->
- io_lib:format("Bad function: ~p(should be atom())~n", [X]);
+ io_lib:format("Bad function: ~tp(should be atom())~n", [X]);
format_error({bad_lib, X}) ->
- io_lib:format("Bad library: ~p(should be atom())~n", [X]);
+ io_lib:format("Bad library: ~tp(should be atom())~n", [X]);
format_error({bad_lib_vsn, X}) ->
- io_lib:format("Bad library version: ~p(should be string())~n", [X]);
+ io_lib:format("Bad library version: ~tp(should be string())~n", [X]);
format_error({bad_timeout, X}) ->
- io_lib:format("Bad timeout: ~p(should be infinity | int() > 0)~n", [X]);
+ io_lib:format("Bad timeout: ~tp(should be infinity | int() > 0)~n", [X]);
format_error({undef_module, Mod}) ->
io_lib:format("Undefined module: ~p~n", [Mod]);
format_error({muldef_module, Mod}) ->
io_lib:format("Multiply defined module: ~p~n", [Mod]);
format_error(E) ->
- io_lib:format("~p~n",[E]).
+ io_lib:format("~tp~n",[E]).
%%-----------------------------------------------------------------
diff --git a/lib/sasl/src/systools_relup.erl b/lib/sasl/src/systools_relup.erl
index 6bc26c8cc9..e836d57670 100644
--- a/lib/sasl/src/systools_relup.erl
+++ b/lib/sasl/src/systools_relup.erl
@@ -535,9 +535,9 @@ to_list(X) when is_list(X) -> X.
write_relup_file(Relup, Opts) ->
Filename = filename:join(filename:absname(get_opt(outdir,Opts)),
"relup"),
- case file:open(Filename, [write]) of
+ case file:open(Filename, [write,{encoding,utf8}]) of
{ok, Fd} ->
- io:format(Fd, "~p.~n", [Relup]),
+ io:format(Fd, "%% ~s~n~tp.~n", [epp:encoding_to_string(utf8),Relup]),
case file:close(Fd) of
ok -> ok;
{error,Reason} ->
@@ -589,7 +589,7 @@ print_error({error, Mod, Error}) ->
S = apply(Mod, format_error, [Error]),
io:format(S, []);
print_error(Other) ->
- io:format("Error: ~p~n", [Other]).
+ io:format("Error: ~tp~n", [Other]).
format_error({file_problem, {File, What}}) ->
io_lib:format("Could not ~w file ~ts~n", [get_reason(What), File]);
@@ -606,7 +606,7 @@ format_error({warnings_treated_as_errors, Warnings}) ->
io_lib:format("Warnings being treated as errors:~n~ts",
[[format_warning("",W) || W <- Warnings]]);
format_error(Error) ->
- io_lib:format("~p~n", [Error]).
+ io_lib:format("~tp~n", [Error]).
print_warnings(Ws) when is_list(Ws) ->
@@ -621,12 +621,12 @@ format_warning(W) ->
format_warning("*WARNING* ", W).
format_warning(Prefix, {erts_vsn_changed, {Rel1, Rel2}}) ->
- io_lib:format("~tsThe ERTS version changed between ~p and ~p~n",
+ io_lib:format("~tsThe ERTS version changed between ~tp and ~tp~n",
[Prefix, Rel1, Rel2]);
format_warning(Prefix, pre_R15_emulator_upgrade) ->
io_lib:format("~tsUpgrade from an OTP version earlier than R15. New code should be compiled with the old emulator.~n",[Prefix]);
format_warning(Prefix, What) ->
- io_lib:format("~ts~p~n",[Prefix, What]).
+ io_lib:format("~ts~tp~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 7093158502..50932e89e4 100644
--- a/lib/sasl/test/release_handler_SUITE.erl
+++ b/lib/sasl/test/release_handler_SUITE.erl
@@ -66,7 +66,7 @@ cases() ->
supervisor_which_children_timeout,
release_handler_which_releases, install_release_syntax_check,
upgrade_supervisor, upgrade_supervisor_fail, otp_9864,
- otp_10463_upgrade_script_regexp, no_dot_erlang].
+ otp_10463_upgrade_script_regexp, no_dot_erlang, unicode_upgrade].
groups() ->
[{release,[],
@@ -1875,6 +1875,86 @@ no_dot_erlang(Conf) ->
ok
end.
+%%%-----------------------------------------------------------------
+%%% Test unicode handling. Make sure that release name, application
+%%% description, and application environment variables may contain
+%%% unicode characters.
+unicode_upgrade(Conf) ->
+ %% Set some paths
+ DataDir = ?config(data_dir, Conf),
+ PrivDir = priv_dir(Conf),
+ Dir = filename:join(PrivDir,"unicode"),
+ LibDir0 = filename:join(DataDir, "unicode"),
+ LibDir =
+ case {file:native_name_encoding(),os:type()} of
+ {utf8,{Os,_}} when Os =/= win32 ->
+ LD = filename:join(DataDir,"unicode_αβ"),
+ file:make_symlink("unicode",LD),
+ LD;
+ _ ->
+ LibDir0
+ end,
+
+ %% Create the releases
+ RelName = "unicode_rel_αβ",
+ Rel1 = create_and_install_fake_first_release(Dir,{RelName,"1"},
+ [{u,"1.0",LibDir}]),
+ Rel2 = create_fake_upgrade_release(Dir,
+ {RelName,"2"},
+ [{u,"1.1",LibDir}],
+ {[Rel1],[Rel1],[LibDir]}),
+ Rel1Dir = filename:dirname(Rel1),
+ Rel2Dir = filename:dirname(Rel2),
+
+ %% Start a slave node
+ {ok, Node} = t_start_node(unicode_upgrade, Rel1,
+ filename:join(Rel1Dir,"sys.config"), "+pc unicode"),
+
+ %% Check
+ Dir1 = filename:join([LibDir, "u-1.0"]),
+ Dir1 = rpc:call(Node, code, lib_dir, [u]),
+ UBeam1 = filename:join([Dir1,"ebin","u.beam"]),
+ UBeam1 = rpc:call(Node,code,which,[u]),
+ {RelName,"1"} = rpc:call(Node,init,script_id,[]),
+ {Env,state} = rpc:call(Node,u,u,[]),
+ 'val_αβ' = proplists:get_value('key_αβ',Env),
+ [{RelName,"1",_,permanent}|_] =
+ rpc:call(Node,release_handler,which_releases,[]),
+ {ok,ReleasesDir} = rpc:call(Node,application,get_env,[sasl,releases_dir]),
+ {ok,[[{release,RelName,"1",_,_,permanent}|_]]} =
+ file:consult(filename:join(ReleasesDir,"RELEASES")),
+
+ %% Install second release
+ {ok, RelVsn2} =
+ rpc:call(Node, release_handler, set_unpacked,
+ [Rel2++".rel", [{u,"1.1",LibDir}]]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "relup")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "start.boot")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "sys.config")]),
+
+ {ok, _RelVsn1, []} =
+ rpc:call(Node, release_handler, install_release, [RelVsn2]),
+
+ %% And check
+ Dir2 = filename:join([LibDir, "u-1.1"]),
+ Dir2 = rpc:call(Node, code, lib_dir, [u]),
+ UBeam2 = filename:join([Dir2,"ebin","u.beam"]),
+ {file,UBeam2} = rpc:call(Node,code,is_loaded,[u]),
+ {RelName,"1"} = rpc:call(Node,init,script_id,[]),
+ {Env,{state,'αβ'}} = rpc:call(Node,u,u,[]),
+ [{RelName,"2",_,current}|_] =
+ rpc:call(Node,release_handler,which_releases,[]),
+ {ok,ReleasesDir2} = rpc:call(Node,application,get_env,[sasl,releases_dir]),
+ {ok,<<"%% coding: utf-8\n[{release,\"unicode_rel_αβ\",\"2\""/utf8,_/binary>>}=
+ file:read_file(filename:join(ReleasesDir2,"RELEASES")),
+ ok.
+
+unicode_upgrade(cleanup,_Conf) ->
+ stop_node(node_name(unicode_upgrade)).
+
%%%=================================================================
%%% Misceleaneous functions
@@ -2002,6 +2082,8 @@ are_names_reg_gg(Node, Names, N) ->
t_start_node(Name, Boot, SysConfig) ->
+ t_start_node(Name, Boot, SysConfig, "").
+t_start_node(Name, Boot, SysConfig, ArgStr) ->
Args =
case Boot of
[] -> [];
@@ -2010,8 +2092,9 @@ t_start_node(Name, Boot, SysConfig) ->
case SysConfig of
[] -> [];
_ -> " -config " ++ SysConfig
- end,
- test_server:start_node(Name, slave, [{args, Args}]).
+ end ++
+ " " ++ ArgStr,
+ test_server:start_node(Name, peer, [{args, Args}]).
stop_node(Node) ->
?t:stop_node(Node).
@@ -2460,7 +2543,9 @@ create_rel_file(RelFile,RelName,RelVsn,Erts,ExtraApps) ->
%% Insert a term in a file, which can be read with file:consult/1.
write_term_file(File,Term) ->
- ok = file:write_file(File,io_lib:format("~p.~n",[Term])).
+ Str = io_lib:format("%% ~s~n~tp.~n",[epp:encoding_to_string(utf8),Term]),
+ Bin = unicode:characters_to_binary(Str),
+ ok = file:write_file(File,Bin).
%% Check that global group info is correct - try again for a maximum of 5 sec
@@ -2719,8 +2804,8 @@ cover_fun(Node,Func) ->
%% and possibly other applications if they are listed in AppDirs =
%% [{App,Vsn,LibDir}]
create_and_install_fake_first_release(Dir,AppDirs) ->
- %% Create the first release
- {RelName,RelVsn} = init:script_id(),
+ create_and_install_fake_first_release(Dir,init:script_id(),AppDirs).
+create_and_install_fake_first_release(Dir,{RelName,RelVsn},AppDirs) ->
{Rel,_} = create_fake_release(Dir,RelName,RelVsn,AppDirs),
ReleasesDir = filename:join(Dir, "releases"),
RelDir = filename:dirname(Rel),
@@ -2744,9 +2829,11 @@ create_and_install_fake_first_release(Dir,AppDirs) ->
%% be upgraded to from the release created by
%% create_and_install_fake_first_release/2. Unpack first by calls to
%% release_handler:set_unpacked and release_handler:install_file.
-create_fake_upgrade_release(Dir,RelVsn,AppDirs,{UpFrom,DownTo,ExtraLibs}) ->
- %% Create a new release
+create_fake_upgrade_release(Dir,RelVsn,AppDirs,UpgrInstr) when not is_tuple(RelVsn) ->
{RelName,_} = init:script_id(),
+ create_fake_upgrade_release(Dir,{RelName,RelVsn},AppDirs,UpgrInstr);
+create_fake_upgrade_release(Dir,{RelName,RelVsn},AppDirs,{UpFrom,DownTo,ExtraLibs}) ->
+ %% Create a new release
{Rel,Paths} = create_fake_release(Dir,RelName,RelVsn,AppDirs),
RelDir = filename:dirname(Rel),
diff --git a/lib/sasl/test/release_handler_SUITE_data/Makefile.src b/lib/sasl/test/release_handler_SUITE_data/Makefile.src
index b794aa0e6f..113d3e2290 100644
--- a/lib/sasl/test/release_handler_SUITE_data/Makefile.src
+++ b/lib/sasl/test/release_handler_SUITE_data/Makefile.src
@@ -76,7 +76,13 @@ SUP= \
release_handler_timeouts/dummy-0.1/ebin/dummy_sup.@EMULATOR@ \
release_handler_timeouts/dummy-0.1/ebin/dummy_sup_2.@EMULATOR@
-all: $(LIB) $(APP) $(OTP2740) $(C) $(SUP)
+UNICODE= \
+ unicode/u-1.0/ebin/u.@EMULATOR@ \
+ unicode/u-1.0/ebin/u_sup.@EMULATOR@ \
+ unicode/u-1.1/ebin/u.@EMULATOR@ \
+ unicode/u-1.1/ebin/u_sup.@EMULATOR@
+
+all: $(LIB) $(APP) $(OTP2740) $(C) $(SUP) $(UNICODE)
lib/a-1.0/ebin/a.@EMULATOR@: lib/a-1.0/src/a.erl
erlc $(EFLAGS) -olib/a-1.0/ebin lib/a-1.0/src/a.erl
@@ -236,3 +242,13 @@ release_handler_timeouts/dummy-0.1/ebin/dummy_sup.@EMULATOR@: release_handler_ti
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
+
+unicode/u-1.0/ebin/u.@EMULATOR@: unicode/u-1.0/src/u.erl
+ erlc $(EFLAGS) -ounicode/u-1.0/ebin unicode/u-1.0/src/u.erl
+unicode/u-1.0/ebin/u_sup.@EMULATOR@: unicode/u-1.0/src/u_sup.erl
+ erlc $(EFLAGS) -ounicode/u-1.0/ebin unicode/u-1.0/src/u_sup.erl
+
+unicode/u-1.1/ebin/u.@EMULATOR@: unicode/u-1.1/src/u.erl
+ erlc $(EFLAGS) -ounicode/u-1.1/ebin unicode/u-1.1/src/u.erl
+unicode/u-1.1/ebin/u_sup.@EMULATOR@: unicode/u-1.1/src/u_sup.erl
+ erlc $(EFLAGS) -ounicode/u-1.1/ebin unicode/u-1.1/src/u_sup.erl
diff --git a/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.0/ebin/u.app b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.0/ebin/u.app
new file mode 100644
index 0000000000..fea4f9992e
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.0/ebin/u.app
@@ -0,0 +1,8 @@
+{application, u,
+ [{description, "This app shall test unicode handling αβ"},
+ {vsn, "1.0"},
+ {modules, [u, u_sup]},
+ {registered, [u_sup]},
+ {applications, [kernel, stdlib]},
+ {env, [{'key_αβ', 'val_αβ'}]},
+ {mod, {u_sup, []}}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.0/src/u.erl b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.0/src/u.erl
new file mode 100644
index 0000000000..45fe098c0e
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.0/src/u.erl
@@ -0,0 +1,50 @@
+%% ``Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
+%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
+%% AB. All Rights Reserved.''
+%%
+%% $Id$
+%%
+-module(u).
+
+
+-behaviour(gen_server).
+
+-vsn(1).
+
+%% External exports
+-export([start_link/0, u/0]).
+%% Internal exports
+-export([init/1, handle_call/3, handle_info/2, terminate/2]).
+
+start_link() -> gen_server:start_link({local, uu}, u, [], []).
+
+u() -> gen_server:call(uu, u).
+
+%%-----------------------------------------------------------------
+%% Callback functions from gen_server
+%%-----------------------------------------------------------------
+init([]) ->
+ process_flag(trap_exit, true),
+ {ok, state}.
+
+handle_call(u, _From, State) ->
+ X = application:get_all_env(u),
+ {reply, {X,State}, State}.
+
+handle_info(_, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
diff --git a/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.0/src/u_sup.erl b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.0/src/u_sup.erl
new file mode 100644
index 0000000000..b0d4a7b58f
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.0/src/u_sup.erl
@@ -0,0 +1,38 @@
+%% ``Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
+%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
+%% AB. All Rights Reserved.''
+%%
+%% $Id$
+%%
+-module(u_sup).
+
+
+-behaviour(supervisor).
+
+%% External exports
+-export([start/2]).
+
+%% Internal exports
+-export([init/1]).
+
+start(_, _) ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+init([]) ->
+ SupFlags = {one_for_one, 4, 3600},
+ Config = {u,
+ {u, start_link, []},
+ permanent, 2000, worker, [u]},
+ {ok, {SupFlags, [Config]}}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/ebin/u.app b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/ebin/u.app
new file mode 100644
index 0000000000..8fcc3bba42
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/ebin/u.app
@@ -0,0 +1,8 @@
+{application, u,
+ [{description, "This app shall test unicode handling αβ"},
+ {vsn, "1.1"},
+ {modules, [u, u_sup]},
+ {registered, [u_sup]},
+ {applications, [kernel, stdlib]},
+ {env, [{'key_αβ', 'val_αβ'}]},
+ {mod, {u_sup, []}}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/ebin/u.appup b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/ebin/u.appup
new file mode 100644
index 0000000000..0344ce92ab
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/ebin/u.appup
@@ -0,0 +1,3 @@
+{"1.1",
+ [{"1.0",[{update,u,{advanced,'αβ'}}]}],
+ [{"1.0",[{update,u,{advanced,'αβ'}}]}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/src/u.erl b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/src/u.erl
new file mode 100644
index 0000000000..d2544d6fc1
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/src/u.erl
@@ -0,0 +1,55 @@
+%% ``Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
+%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
+%% AB. All Rights Reserved.''
+%%
+%% $Id$
+%%
+-module(u).
+
+
+-behaviour(gen_server).
+
+-vsn(1).
+
+%% External exports
+-export([start_link/0, u/0]).
+%% Internal exports
+-export([init/1, handle_call/3, handle_info/2, terminate/2, code_change/3]).
+
+start_link() -> gen_server:start_link({local, uu}, u, [], []).
+
+u() -> gen_server:call(uu, u).
+
+%%-----------------------------------------------------------------
+%% Callback functions from gen_server
+%%-----------------------------------------------------------------
+init([]) ->
+ process_flag(trap_exit, true),
+ {ok, {state,'αβ'}}.
+
+handle_call(u, _From, State) ->
+ X = application:get_all_env(u),
+ {reply, {X,State}, State}.
+
+handle_info(_, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change({down,_}, {State,_}, _Extra) ->
+ {ok, State};
+code_change(_, State, Extra) ->
+ {ok, {State, Extra}}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/src/u_sup.erl b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/src/u_sup.erl
new file mode 100644
index 0000000000..b0d4a7b58f
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/src/u_sup.erl
@@ -0,0 +1,38 @@
+%% ``Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
+%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
+%% AB. All Rights Reserved.''
+%%
+%% $Id$
+%%
+-module(u_sup).
+
+
+-behaviour(supervisor).
+
+%% External exports
+-export([start/2]).
+
+%% Internal exports
+-export([init/1]).
+
+start(_, _) ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+init([]) ->
+ SupFlags = {one_for_one, 4, 3600},
+ Config = {u,
+ {u, start_link, []},
+ permanent, 2000, worker, [u]},
+ {ok, {SupFlags, [Config]}}.
diff --git a/lib/sasl/test/sasl_report_SUITE.erl b/lib/sasl/test/sasl_report_SUITE.erl
index aa229726ae..53fb614921 100644
--- a/lib/sasl/test/sasl_report_SUITE.erl
+++ b/lib/sasl/test/sasl_report_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -79,7 +79,7 @@ do_gen_server_crash(Config) ->
error_logger:logfile(close),
check_file(KernelLog, 70000, 150000),
- check_file(SaslLog, 50000, 100000),
+ check_file(SaslLog, 100000, 150000),
ok.
diff --git a/lib/sasl/vsn.mk b/lib/sasl/vsn.mk
index 6aa662a743..2608ca5e00 100644
--- a/lib/sasl/vsn.mk
+++ b/lib/sasl/vsn.mk
@@ -1 +1 @@
-SASL_VSN = 3.0.3
+SASL_VSN = 3.0.4