aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPéter Gömöri <[email protected]>2015-05-29 19:00:33 +0200
committerBjörn Gustavsson <[email protected]>2015-06-10 11:44:33 +0200
commitb1012c31f38810c6754dcd4cf03f8d2bfb010506 (patch)
tree69c72ec0d08163565471a7cb86f567fa3c2259f7
parent23501295ea5289897a75cb52a23685f8e6fcf18c (diff)
downloadotp-b1012c31f38810c6754dcd4cf03f8d2bfb010506.tar.gz
otp-b1012c31f38810c6754dcd4cf03f8d2bfb010506.tar.bz2
otp-b1012c31f38810c6754dcd4cf03f8d2bfb010506.zip
cover: handle undefined module when analysing to file
It is possible that not just the source but even the beam of a module is not available when calling analyse_to_file. For example when coverdata is imported from an old file and since then a module was removed. Before this fix cover:analyse_to_file/3 could possibly never return because of a helper process crashed with error:undef and never reply to the caller. At the same time link the helper process to cover_server so any further error won't let the caller waiting indefinitely.
-rw-r--r--lib/tools/src/cover.erl10
-rw-r--r--lib/tools/test/cover_SUITE.erl43
-rw-r--r--lib/tools/test/cover_SUITE_data/compile_beam/t.erl6
3 files changed, 55 insertions, 4 deletions
diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl
index 71e17e0ba1..24881a0ab0 100644
--- a/lib/tools/src/cover.erl
+++ b/lib/tools/src/cover.erl
@@ -782,7 +782,7 @@ main_process_loop(State) ->
{From, {{analyse_to_file, Opts},Module}} ->
S = try
Loaded = is_loaded(Module, State),
- spawn(fun() ->
+ spawn_link(fun() ->
?SPAWN_DBG(analyse_to_file,{Module,Opts}),
do_parallel_analysis_to_file(
Module, Opts, Loaded, From, State)
@@ -2143,7 +2143,13 @@ find_source(Module, File0) ->
throw_file(filename:join([BeamDir, "..", "src", Base])),
%% Not in ../src: look for source path in compile info, but
%% first look relative the beam directory.
- Info = lists:keyfind(source, 1, Module:module_info(compile)),
+ Info =
+ try lists:keyfind(source, 1, Module:module_info(compile))
+ catch error:undef ->
+ %% The module might have been imported
+ %% and the beam not available
+ throw({beam, File0})
+ end,
false == Info andalso throw({beam, File0}), %% stripped
{source, SrcFile} = Info,
throw_file(splice(BeamDir, SrcFile)), %% below ../src
diff --git a/lib/tools/test/cover_SUITE.erl b/lib/tools/test/cover_SUITE.erl
index 368fa6c3d1..bc85f3c045 100644
--- a/lib/tools/test/cover_SUITE.erl
+++ b/lib/tools/test/cover_SUITE.erl
@@ -29,7 +29,8 @@
export_import/1,
otp_5031/1, eif/1, otp_5305/1, otp_5418/1, otp_6115/1, otp_7095/1,
otp_8188/1, otp_8270/1, otp_8273/1, otp_8340/1,
- otp_10979_hanging_node/1, compile_beam_opts/1, eep37/1]).
+ otp_10979_hanging_node/1, compile_beam_opts/1, eep37/1,
+ analyse_no_beam/1]).
-export([do_coverage/1]).
@@ -52,7 +53,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
NoStartStop = [eif,otp_5305,otp_5418,otp_7095,otp_8273,
- otp_8340,otp_8188,compile_beam_opts,eep37],
+ otp_8340,otp_8188,compile_beam_opts,eep37,
+ analyse_no_beam],
StartStop = [start, compile, analyse, misc, stop,
distribution, reconnect, die_and_reconnect,
dont_reconnect_after_stop, stop_node_after_disconnect,
@@ -1687,6 +1689,43 @@ compile_beam_opts(Config) when is_list(Config) ->
ok = file:set_cwd(Cwd),
ok.
+analyse_no_beam(doc) ->
+ ["Don't crash if beam is not available"];
+analyse_no_beam(suite) -> [];
+analyse_no_beam(Config) when is_list(Config) ->
+ {ok, Cwd} = file:get_cwd(),
+ ok = file:set_cwd(?config(data_dir, Config)),
+
+ code:purge(t),
+ code:delete(t),
+
+ {ok,_} = file:copy("compile_beam/t.erl", "t.erl"),
+ {ok,t} = compile:file(t, [debug_info]),
+ {module,t} = code:load_file(t),
+ {ok,t} = cover:compile_beam(t),
+ t:f(),
+ ok = cover:export("t.coverdata"),
+
+ code:purge(t),
+ code:delete(t),
+
+ %% this is just so that cover realises (without stopping)
+ %% that this module is not cover compiled any more
+ {error, {not_cover_compiled,t}} = cover:analyse(t),
+
+ %% source and beam not available any more
+ ok = file:delete("t.erl"),
+ ok = file:delete("t.beam"),
+
+ ok = cover:import("t.coverdata"),
+
+ {error,{no_source_code_found,t}} = cover:analyse_to_file(t),
+ {result,[],[{no_source_code_found,t}]} = cover:analyse_to_file([t]),
+
+ ok = file:delete("t.coverdata"),
+ ok = file:set_cwd(Cwd),
+ ok.
+
%%--Auxiliary------------------------------------------------------------
analyse_expr(Expr, Config) ->
diff --git a/lib/tools/test/cover_SUITE_data/compile_beam/t.erl b/lib/tools/test/cover_SUITE_data/compile_beam/t.erl
new file mode 100644
index 0000000000..96dc2f4209
--- /dev/null
+++ b/lib/tools/test/cover_SUITE_data/compile_beam/t.erl
@@ -0,0 +1,6 @@
+-module(t).
+
+-export([f/0]).
+
+f() ->
+ ok.