summaryrefslogtreecommitdiff
path: root/lib/tools
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tools')
-rw-r--r--lib/tools/src/cover.erl40
-rw-r--r--lib/tools/test/cover_SUITE.erl27
2 files changed, 53 insertions, 14 deletions
diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl
index 8fe866cb69..2b3af417b6 100644
--- a/lib/tools/src/cover.erl
+++ b/lib/tools/src/cover.erl
@@ -196,6 +196,8 @@ start() ->
receive
{?SERVER,started} ->
{ok,Pid};
+ {?SERVER,{error,Error}} ->
+ {error,Error};
{'DOWN', Ref, _Type, _Object, Info} ->
{error,Info}
end,
@@ -645,19 +647,31 @@ remote_reply(MainNode,Reply) ->
%%%----------------------------------------------------------------------
init_main(Starter) ->
- register(?SERVER,self()),
- ?COVER_MAPPING_TABLE = ets:new(?COVER_MAPPING_TABLE,
- [ordered_set, public, named_table]),
- ?COVER_CLAUSE_TABLE = ets:new(?COVER_CLAUSE_TABLE, [set, public,
- named_table]),
- ?BINARY_TABLE = ets:new(?BINARY_TABLE, [set, public, named_table]),
- ?COLLECTION_TABLE = ets:new(?COLLECTION_TABLE, [set, public,
- named_table]),
- ?COLLECTION_CLAUSE_TABLE = ets:new(?COLLECTION_CLAUSE_TABLE, [set, public,
- named_table]),
- ok = net_kernel:monitor_nodes(true),
- Starter ! {?SERVER,started},
- main_process_loop(#main_state{}).
+ try register(?SERVER,self()) of
+ true ->
+ ?COVER_MAPPING_TABLE = ets:new(?COVER_MAPPING_TABLE,
+ [ordered_set, public, named_table]),
+ ?COVER_CLAUSE_TABLE = ets:new(?COVER_CLAUSE_TABLE, [set, public,
+ named_table]),
+ ?BINARY_TABLE = ets:new(?BINARY_TABLE, [set, public, named_table]),
+ ?COLLECTION_TABLE = ets:new(?COLLECTION_TABLE, [set, public,
+ named_table]),
+ ?COLLECTION_CLAUSE_TABLE = ets:new(?COLLECTION_CLAUSE_TABLE,
+ [set, public, named_table]),
+ ok = net_kernel:monitor_nodes(true),
+ Starter ! {?SERVER,started},
+ main_process_loop(#main_state{})
+ catch
+ error:badarg ->
+ %% The server's already registered; either report that it's already
+ %% started or try again if it died before we could find its pid.
+ case whereis(?SERVER) of
+ undefined ->
+ init_main(Starter);
+ Pid ->
+ Starter ! {?SERVER, {error, {already_started, Pid}}}
+ end
+ end.
main_process_loop(State) ->
receive
diff --git a/lib/tools/test/cover_SUITE.erl b/lib/tools/test/cover_SUITE.erl
index ee58fd7a10..462767f430 100644
--- a/lib/tools/test/cover_SUITE.erl
+++ b/lib/tools/test/cover_SUITE.erl
@@ -37,7 +37,7 @@ all() ->
dont_reconnect_after_stop, stop_node_after_disconnect,
export_import, otp_5031, otp_6115,
otp_8270, otp_10979_hanging_node, otp_14817,
- local_only],
+ local_only, startup_race],
case whereis(cover_server) of
undefined ->
[coverage,StartStop ++ NoStartStop];
@@ -1775,7 +1775,32 @@ local_only(Config) ->
{ok,Name} = test_server:start_node(?FUNCTION_NAME, slave, []),
{error,local_only} = cover:start([Name]),
test_server:stop_node(Name),
+ ok.
+%% ERL-943; We should not crash on startup when multiple servers race to
+%% register the server name.
+startup_race(Config) when is_list(Config) ->
+ PidRefs = [spawn_monitor(fun() ->
+ case cover:start() of
+ {error, {already_started, _Pid}} ->
+ ok;
+ {ok, _Pid} ->
+ ok
+ end
+ end) || _<- lists:seq(1,8)],
+ startup_race_1(PidRefs).
+
+startup_race_1([{Pid, Ref} | PidRefs]) ->
+ receive
+ {'DOWN', Ref, process, Pid, normal} ->
+ startup_race_1(PidRefs);
+ {'DOWN', Ref, process, Pid, _Other} ->
+ ct:fail("Cover server crashed on startup.")
+ after 5000 ->
+ ct:fail("Timed out.")
+ end;
+startup_race_1([]) ->
+ cover:stop(),
ok.
%%--Auxiliary------------------------------------------------------------