From bc966c32bfb52467f4fd527995c110c0a980527c Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Tue, 1 Oct 2013 14:16:21 +0200 Subject: sasl: Add no_dot_erlang start script Sometimes it is wanted to start erlang without loading the user dependent .erlang file, for example in scripts and configure tests. --- lib/sasl/src/systools_make.erl | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/sasl/src/systools_make.erl b/lib/sasl/src/systools_make.erl index b2e95fdbee..bab88552f9 100644 --- a/lib/sasl/src/systools_make.erl +++ b/lib/sasl/src/systools_make.erl @@ -1135,10 +1135,10 @@ generate_script(Output, Release, Appls, Flags) -> load_appl_mods(Appls, Mandatory ++ Preloaded, PathFlag, Variables) ++ [{path, create_path(Appls, PathFlag, Variables)}] ++ - create_kernel_procs(Appls) ++ - create_load_appls(Appls) ++ - create_start_appls(Appls) ++ - script_end() + create_kernel_procs(Appls) ++ + create_load_appls(Appls) ++ + create_start_appls(Appls) ++ + script_end(lists:member(no_dot_erlang, Flags)) }, ScriptFile = Output ++ ".script", @@ -1229,9 +1229,12 @@ create_load_appls([]) -> %%______________________________________________________________________ %% The final part of the script. -script_end() -> +script_end(false) -> %% Do not skip loading of $HOME/.erlang [{apply, {c, erlangrc, []}}, - {progress, started}]. + {progress, started}]; +script_end(true) -> %% Ignore loading of $HOME/.erlang + [{progress, started}]. + %%----------------------------------------------------------------- %% Function: sort_appls(Appls) -> {ok, Appls'} | throw({error, Error}) @@ -2055,6 +2058,9 @@ cas([no_warn_sasl | Args], X) -> %%% no_module_tests (kept for backwards compatibility, but ignored) ---- cas([no_module_tests | Args], X) -> cas(Args, X); +cas([no_dot_erlang | Args], X) -> + cas(Args, X); + %%% ERROR -------------------------------------------------------------- cas([Y | Args], X) -> cas(Args, X++[Y]). -- cgit v1.2.3 From a9340a1692b0ae4d3b3c0328d007ac4a7db5cc75 Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Thu, 3 Oct 2013 14:32:38 +0200 Subject: sasl: Add no_dot_erlang documentation and tests --- lib/sasl/doc/src/systools.xml | 6 ++++-- lib/sasl/test/release_handler_SUITE.erl | 33 ++++++++++++++++++++++++++++++++- lib/sasl/test/systools_SUITE.erl | 32 +++++++++++++++++++++++++++++++- 3 files changed, 67 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/sasl/doc/src/systools.xml b/lib/sasl/doc/src/systools.xml index 84fed0a25f..284047163e 100644 --- a/lib/sasl/doc/src/systools.xml +++ b/lib/sasl/doc/src/systools.xml @@ -5,7 +5,7 @@
1996 - 2011 + 2013 Ericsson AB, All Rights Reserved @@ -139,7 +139,7 @@ Name = string() Opt = src_tests | {path,[Dir]} | local | {variables,[Var]} | exref | - {exref,[App]}] | silent | {outdir,Dir} | no_warn_sasl | + {exref,[App]}] | silent | {outdir,Dir} | no_dot_erlang | no_warn_sasl | warnings_as_errors  Dir = string()  Var = {VarName,Prefix} @@ -252,6 +252,8 @@ Module:format_error(Error).

If the option warnings_as_errors is provided, warnings are treated as errors.

+

If the option no_dot_erlang is provided, the instruction to + load the .erlang file during boot is NOT included.

diff --git a/lib/sasl/test/release_handler_SUITE.erl b/lib/sasl/test/release_handler_SUITE.erl index a56924d5ca..d7369b0ecf 100644 --- a/lib/sasl/test/release_handler_SUITE.erl +++ b/lib/sasl/test/release_handler_SUITE.erl @@ -64,7 +64,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]. + otp_10463_upgrade_script_regexp, no_dot_erlang]. groups() -> [{release,[], @@ -1709,6 +1709,37 @@ otp_10463_upgrade_script_regexp(_Config) -> release_handler:upgrade_script(kernel,code:lib_dir(kernel)), ok. +no_dot_erlang(Conf) -> + PrivDir = priv_dir(Conf), + {ok, OrigWd} = file:get_cwd(), + try + ok = file:set_cwd(PrivDir), + + Erl = filename:join([code:root_dir(),"bin","erl"]), + Args = " -noinput -run io put_chars \"TESTOK\" -run erlang halt", + ok = file:write_file(".erlang", <<"io:put_chars(\"DOT_ERLANG_READ\\n\").\n">>), + + case os:cmd(Erl ++ Args) of + "DOT_ERLANG_READ" ++ _ -> ok; + Other1 -> + io:format("Failed: ~s~n",[Erl ++ Args]), + io:format("Expected: ~s ++ _~n",["DOT_ERLANG_READ "]), + io:format("Got: ~s~n",[Other1]), + exit(failed_to_start, test_error) + end, + NO_DOT_ERL = " -boot no_dot_erlang", + case os:cmd(Erl ++ NO_DOT_ERL ++ Args) of + "TESTOK" ++ _ -> ok; + Other2 -> + io:format("Failed: ~s~n",[Erl ++ Args]), + io:format("Expected: ~s~n",["TESTOK"]), + io:format("Got: ~s~n",[Other2]), + exit(failed_to_start, no_dot_erlang) + end + after + _ = file:delete(".erlang"), + ok = file:set_cwd(OrigWd) + end. %%%================================================================= %%% Misceleaneous functions diff --git a/lib/sasl/test/systools_SUITE.erl b/lib/sasl/test/systools_SUITE.erl index 3921b2d3bb..9efc8f8392 100644 --- a/lib/sasl/test/systools_SUITE.erl +++ b/lib/sasl/test/systools_SUITE.erl @@ -43,6 +43,7 @@ -export([script_options/1, normal_script/1, unicode_script/1, unicode_script/2, no_mod_vsn_script/1, wildcard_script/1, variable_script/1, no_sasl_script/1, + no_dot_erlang_script/1, abnormal_script/1, src_tests_script/1, crazy_script/1, included_script/1, included_override_script/1, included_fail_script/1, included_bug_script/1, exref_script/1, @@ -79,7 +80,8 @@ groups() -> [{script, [], [script_options, normal_script, unicode_script, no_mod_vsn_script, wildcard_script, variable_script, abnormal_script, - no_sasl_script, src_tests_script, crazy_script, + no_sasl_script, no_dot_erlang_script, + src_tests_script, crazy_script, included_script, included_override_script, included_fail_script, included_bug_script, exref_script, otp_3065_circular_dependenies, included_and_used_sort_script]}, @@ -457,6 +459,34 @@ no_sasl_script(Config) when is_list(Config) -> ok = file:set_cwd(OldDir), ok. +%% make_script: Create script with no_dot_erlang. Check script contents. +no_dot_erlang_script(Config) when is_list(Config) -> + {ok, OldDir} = file:get_cwd(), + + {LatestDir, LatestName} = create_script(latest1_no_sasl,Config), + + DataDir = filename:absname(?copydir), + LibDir = [fname([DataDir, d_normal, lib])], + P = [fname([LibDir, '*', ebin]), + fname([DataDir, lib, kernel, ebin]), + fname([DataDir, lib, stdlib, ebin]), + fname([DataDir, lib, sasl, ebin])], + + ok = file:set_cwd(LatestDir), + + {ok, _ , []} = + systools:make_script(LatestName,[{path, P},silent, no_warn_sasl]), + {ok, [{_, _, LoadDotErlang}]} = read_script_file(LatestName), + [erlangrc] = [E || {apply, {c, E, []}} <- LoadDotErlang], + + {ok, _ , []} = + systools:make_script(LatestName,[{path, P},silent, no_warn_sasl, no_dot_erlang]), + {ok, [{_, _, DoNotLoadDotErlang}]} = read_script_file(LatestName), + [] = [E || {apply, {c, E, []}} <- DoNotLoadDotErlang], + + ok = file:set_cwd(OldDir), + ok. + %% make_script: Do not check date of object file or that source code %% can be found. -- cgit v1.2.3 From 9237801d22a38d2643ffe94ab626c4d2815012dd Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Thu, 10 Oct 2013 10:55:46 +0200 Subject: mnesia: Synchronize lock cleanup after mnesia down Bad timing could lead to hanging transactions after a mnesia down from a node with sticky locks. Excellent bug report from janchochol Situation: * node A and B have copies of table T * node A ows sticky of table T * node A goes down (e.g. crash) * node B tries to perform transactional operation on table T (e.g. mnesia:select) In this situation there is possibility that first (and maybe other) transaction on node B will hang indefinitely. This is caused by race condition, when transaction process send lock request operation to node A and waits for reply. When node A is down it will never send reply, so process on node B will be stuck forever. Reason is that message sent to mnesia_locker gen_server from mnesia_locker:mnesia_down can be received after mnesia_locker gen_server already replies to transaction processes with {switch, N, Req} and node N is down. Monitoring remote process when sending request to other node should be safe solution. --- lib/mnesia/src/mnesia.appup.src | 14 ++++---------- lib/mnesia/src/mnesia_locker.erl | 32 +++++++++++++++----------------- lib/mnesia/src/mnesia_monitor.erl | 6 +----- lib/mnesia/src/mnesia_tm.erl | 6 ++++-- 4 files changed, 24 insertions(+), 34 deletions(-) (limited to 'lib') diff --git a/lib/mnesia/src/mnesia.appup.src b/lib/mnesia/src/mnesia.appup.src index 355aafb215..c245299740 100644 --- a/lib/mnesia/src/mnesia.appup.src +++ b/lib/mnesia/src/mnesia.appup.src @@ -1,22 +1,16 @@ %% -*- erlang -*- {"%VSN%", [ - {"4.7.1", [{restart_application, mnesia}]}, - {"4.7", [{restart_application, mnesia}]}, - {"4.6", [{restart_application, mnesia}]}, - {"4.5.1", [{restart_application, mnesia}]}, - {"4.5", [{restart_application, mnesia}]}, + {<<"4\\.1[0-9].*">>, [{restart_application, mnesia}]}, + {<<"4\\.[5-9].*">>, [{restart_application, mnesia}]}, {"4.4.19", [{restart_application, mnesia}]}, {"4.4.18", [{restart_application, mnesia}]}, {"4.4.17", [{restart_application, mnesia}]}, {"4.4.16", [{restart_application, mnesia}]} ], [ - {"4.7.1", [{restart_application, mnesia}]}, - {"4.7", [{restart_application, mnesia}]}, - {"4.6", [{restart_application, mnesia}]}, - {"4.5.1", [{restart_application, mnesia}]}, - {"4.5", [{restart_application, mnesia}]}, + {<<"4\\.1[0-9].*">>, [{restart_application, mnesia}]}, + {<<"4\\.[5-9].*">>, [{restart_application, mnesia}]}, {"4.4.19", [{restart_application, mnesia}]}, {"4.4.18", [{restart_application, mnesia}]}, {"4.4.17", [{restart_application, mnesia}]}, diff --git a/lib/mnesia/src/mnesia_locker.erl b/lib/mnesia/src/mnesia_locker.erl index 14011003d3..c4fe370ec1 100644 --- a/lib/mnesia/src/mnesia_locker.erl +++ b/lib/mnesia/src/mnesia_locker.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2012. All Rights Reserved. +%% Copyright Ericsson AB 1996-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -26,8 +26,8 @@ global_lock/5, ixrlock/5, init/1, - mnesia_down/2, release_tid/1, + mnesia_down/2, async_release_tid/2, send_release_tid/2, receive_release_tid_acc/2, @@ -137,6 +137,17 @@ receive_release_tid_acc([Node | Nodes], Tid) -> receive_release_tid_acc([], _Tid) -> ok. +mnesia_down(Node, Pending) -> + case whereis(?MODULE) of + undefined -> {error, node_not_running}; + Pid -> + Ref = make_ref(), + Pid ! {{self(), Ref}, {release_remote_non_pending, Node, Pending}}, + receive %% No need to wait for anything else if process dies we die soon + {Ref,ok} -> ok + end + end. + loop(State) -> receive {From, {write, Tid, Oid}} -> @@ -213,9 +224,9 @@ loop(State) -> reply(From, {tid_released, Tid}), loop(State); - {release_remote_non_pending, Node, Pending} -> + {{From, Ref},{release_remote_non_pending, Node, Pending}} -> release_remote_non_pending(Node, Pending), - mnesia_monitor:mnesia_down(?MODULE, Node), + From ! {Ref, ok}, loop(State); {'EXIT', Pid, _} when Pid == State#state.supervisor -> @@ -653,19 +664,6 @@ ix_read_res(Tab,IxKey,Pos) -> %% ********************* end server code ******************** %% The following code executes at the client side of a transactions -mnesia_down(N, Pending) -> - case whereis(?MODULE) of - undefined -> - %% Takes care of mnesia_down's in early startup - mnesia_monitor:mnesia_down(?MODULE, N); - Pid -> - %% Syncronously call needed in order to avoid - %% race with mnesia_tm's coordinator processes - %% that may restart and acquire new locks. - %% mnesia_monitor ensures the sync. - Pid ! {release_remote_non_pending, N, Pending} - end. - %% Aquire a write lock, but do a read, used by %% mnesia:wread/1 diff --git a/lib/mnesia/src/mnesia_monitor.erl b/lib/mnesia/src/mnesia_monitor.erl index 7a788238fc..438da65158 100644 --- a/lib/mnesia/src/mnesia_monitor.erl +++ b/lib/mnesia/src/mnesia_monitor.erl @@ -482,11 +482,7 @@ handle_cast({mnesia_down, mnesia_controller, Node}, State) -> mnesia_tm:mnesia_down(Node), {noreply, State}; -handle_cast({mnesia_down, mnesia_tm, {Node, Pending}}, State) -> - mnesia_locker:mnesia_down(Node, Pending), - {noreply, State}; - -handle_cast({mnesia_down, mnesia_locker, Node}, State) -> +handle_cast({mnesia_down, mnesia_tm, Node}, State) -> Down = {mnesia_down, Node}, mnesia_lib:report_system_event(Down), GoingDown = lists:delete(Node, State#state.going_down), diff --git a/lib/mnesia/src/mnesia_tm.erl b/lib/mnesia/src/mnesia_tm.erl index e54e5c4e88..17af0cad44 100644 --- a/lib/mnesia/src/mnesia_tm.erl +++ b/lib/mnesia/src/mnesia_tm.erl @@ -181,7 +181,7 @@ mnesia_down(Node) -> %% mnesia_monitor takes care of the sync case whereis(?MODULE) of undefined -> - mnesia_monitor:mnesia_down(?MODULE, {Node, []}); + mnesia_monitor:mnesia_down(?MODULE, Node); Pid -> Pid ! {mnesia_down, Node} end. @@ -403,7 +403,9 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor= Tids = gb_trees:keys(Participants), reconfigure_participants(N, gb_trees:values(Participants)), NewState = clear_fixtable(N, State), - mnesia_monitor:mnesia_down(?MODULE, {N, Tids}), + + mnesia_locker:mnesia_down(N, Tids), + mnesia_monitor:mnesia_down(?MODULE, N), doit_loop(NewState); {From, {unblock_me, Tab}} -> -- cgit v1.2.3