Skip to content

Commit 5e01905

Browse files
committed
horus: Work around race in cover:is_compiled/1
[Why] The `cover:call/1` internal checks if the cover server is running and starts it if it's not: Ref = erlang:monitor(process,?SERVER), receive {'DOWN', Ref, _Type, _Object, noproc} -> erlang:demonitor(Ref), {ok,_} = start(), ... However, there is no lock between the check and the start. Therefore, any concurrent uses of this code may cause a `badmatch` crash on `{ok,_} = start()` because it might have been started in parallel and the function returns the `already_started` error. [How] To work around the problem, we catch the `badmatch` and retry once after a sleep of 100 ms. We don't try to catch any exception from that second attempt.
1 parent 3e9907d commit 5e01905

File tree

1 file changed

+13
-1
lines changed

1 file changed

+13
-1
lines changed

src/horus.erl

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1998,7 +1998,7 @@ get_object_code(Module) ->
19981998
%% @private
19991999

20002000
do_get_object_code(Module) ->
2001-
case cover:is_compiled(Module) of
2001+
case is_cover_compiled(Module) of
20022002
false ->
20032003
get_object_code_from_code_server(Module);
20042004
{file, Filename} ->
@@ -2008,6 +2008,18 @@ do_get_object_code(Module) ->
20082008
erpc:call(CoverMainNode, ?MODULE, do_get_object_code, [Module])
20092009
end.
20102010

2011+
is_cover_compiled(Module) ->
2012+
try
2013+
cover:is_compiled(Module)
2014+
catch
2015+
error:{badmatch, {error, {already_started, _}}} ->
2016+
%% The code in `cover' that checks if the cover server is started
2017+
%% seem racy. We get an exception if it thinks it has to start it
2018+
%% but it is already started. In this case, we retry the call.
2019+
timer:sleep(100),
2020+
cover:is_compiled(Module)
2021+
end.
2022+
20112023
get_object_code_from_code_server(Module) ->
20122024
case code:get_object_code(Module) of
20132025
{Module, Beam, Filename} ->

0 commit comments

Comments
 (0)