aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorTuncer Ayaz <[email protected]>2011-09-01 18:10:41 +0200
committerTuncer Ayaz <[email protected]>2012-07-06 17:01:02 +0200
commit449a093a22af91403c36ca45c620d648d9110ab5 (patch)
treebd14241b3f7aadc92047c42c84a1181f257f409e /lib
parentc075ac6484e3d5a93a0d870ab4483d39ae26eaec (diff)
downloadotp-449a093a22af91403c36ca45c620d648d9110ab5.tar.gz
otp-449a093a22af91403c36ca45c620d648d9110ab5.tar.bz2
otp-449a093a22af91403c36ca45c620d648d9110ab5.zip
[erts,kernel,stdlib] fix escript/primary archive reloading
If the mtime of an escript/primary archive file changes after being added to the code path, correctly reload the archive and update the cache. The existing code didn't consider that it might be a zip archive and failed: =ERROR REPORT==== 3-Aug-2011::09:21:21 === File operation error: bad_central_directory. Target: /escript_archive/module.beam. Function: get_file. Process: code_server. Thanks David Reid and Hakan Mattson.
Diffstat (limited to 'lib')
-rw-r--r--lib/kernel/src/code.erl13
-rw-r--r--lib/kernel/src/code_server.erl4
-rw-r--r--lib/kernel/test/erl_prim_loader_SUITE.erl8
-rw-r--r--lib/stdlib/src/escript.erl18
-rw-r--r--lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_main2.erl17
5 files changed, 48 insertions, 12 deletions
diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl
index b7fda69ce0..363072951e 100644
--- a/lib/kernel/src/code.erl
+++ b/lib/kernel/src/code.erl
@@ -63,7 +63,7 @@
which/1,
where_is_file/1,
where_is_file/2,
- set_primary_archive/3,
+ set_primary_archive/4,
clash/0]).
-export_type([load_error_rsn/0, load_ret/0]).
@@ -107,7 +107,7 @@
%% unstick_mod(Module) -> true
%% is_sticky(Module) -> boolean()
%% which(Module) -> Filename | loaded_ret_atoms() | non_existing
-%% set_primary_archive((FileName, Bin, FileInfo) -> ok | {error, Reason}
+%% set_primary_archive((FileName, ArchiveBin, FileInfo, ParserFun) -> ok | {error, Reason}
%% clash() -> ok prints out number of clashes
%%----------------------------------------------------------------------------
@@ -481,13 +481,16 @@ where_is_file(Path, File) when is_list(Path), is_list(File) ->
-spec set_primary_archive(ArchiveFile :: file:filename(),
ArchiveBin :: binary(),
- FileInfo :: file:file_info())
+ FileInfo :: file:file_info(),
+ ParserFun :: fun())
-> 'ok' | {'error', atom()}.
-set_primary_archive(ArchiveFile0, ArchiveBin, #file_info{} = FileInfo)
+set_primary_archive(ArchiveFile0, ArchiveBin, #file_info{} = FileInfo,
+ ParserFun)
when is_list(ArchiveFile0), is_binary(ArchiveBin) ->
ArchiveFile = filename:absname(ArchiveFile0),
- case call({set_primary_archive, ArchiveFile, ArchiveBin, FileInfo}) of
+ case call({set_primary_archive, ArchiveFile, ArchiveBin, FileInfo,
+ ParserFun}) of
{ok, []} ->
ok;
{ok, _Mode, Ebins} ->
diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl
index a2db7c9790..00ad923466 100644
--- a/lib/kernel/src/code_server.erl
+++ b/lib/kernel/src/code_server.erl
@@ -394,8 +394,8 @@ handle_call(stop,{_From,_Tag}, S) ->
handle_call({is_cached,_File}, {_From,_Tag}, S=#state{cache=no_cache}) ->
{reply, no, S};
-handle_call({set_primary_archive, File, ArchiveBin, FileInfo}, {_From,_Tag}, S=#state{mode=Mode}) ->
- case erl_prim_loader:set_primary_archive(File, ArchiveBin, FileInfo) of
+handle_call({set_primary_archive, File, ArchiveBin, FileInfo, ParserFun}, {_From,_Tag}, S=#state{mode=Mode}) ->
+ case erl_prim_loader:set_primary_archive(File, ArchiveBin, FileInfo, ParserFun) of
{ok, Files} ->
{reply, {ok, Mode, Files}, S};
{error, _Reason} = Error ->
diff --git a/lib/kernel/test/erl_prim_loader_SUITE.erl b/lib/kernel/test/erl_prim_loader_SUITE.erl
index 6f4f27d594..72239641e9 100644
--- a/lib/kernel/test/erl_prim_loader_SUITE.erl
+++ b/lib/kernel/test/erl_prim_loader_SUITE.erl
@@ -426,7 +426,9 @@ primary_archive(Config) when is_list(Config) ->
ExpectedEbins = [Archive, DictDir ++ "/ebin", DummyDir ++ "/ebin"],
io:format("ExpectedEbins: ~p\n", [ExpectedEbins]),
?line {ok, FileInfo} = prim_file:read_file_info(Archive),
- ?line {ok, Ebins} = rpc:call(Node, erl_prim_loader, set_primary_archive, [Archive, ArchiveBin, FileInfo]),
+ ?line {ok, Ebins} = rpc:call(Node, erl_prim_loader, set_primary_archive,
+ [Archive, ArchiveBin, FileInfo,
+ fun escript:parse_file/1]),
?line ExpectedEbins = lists:sort(Ebins), % assert
?line {ok, TopFiles2} = rpc:call(Node, erl_prim_loader, list_dir, [Archive]),
@@ -435,7 +437,9 @@ primary_archive(Config) when is_list(Config) ->
?line ok = test_archive(Node, Archive, DictDir, BeamName),
%% Cleanup
- ?line {ok, []} = rpc:call(Node, erl_prim_loader, set_primary_archive, [undefined, undefined, undefined]),
+ ?line {ok, []} = rpc:call(Node, erl_prim_loader, set_primary_archive,
+ [undefined, undefined, undefined,
+ fun escript:parse_file/1]),
?line stop_node(Node),
?line ok = file:delete(Archive),
ok.
diff --git a/lib/stdlib/src/escript.erl b/lib/stdlib/src/escript.erl
index 27e70ac4d4..498d850df3 100644
--- a/lib/stdlib/src/escript.erl
+++ b/lib/stdlib/src/escript.erl
@@ -22,7 +22,7 @@
-export([script_name/0, create/2, extract/2]).
%% Internal API.
--export([start/0, start/1]).
+-export([start/0, start/1, parse_file/1]).
%%-----------------------------------------------------------------------
@@ -346,7 +346,8 @@ parse_and_run(File, Args, Options) ->
case Source of
archive ->
{ok, FileInfo} = file:read_file_info(File),
- case code:set_primary_archive(File, FormsOrBin, FileInfo) of
+ case code:set_primary_archive(File, FormsOrBin, FileInfo,
+ fun escript:parse_file/1) of
ok when CheckOnly ->
case code:load_file(Module) of
{module, _} ->
@@ -396,6 +397,19 @@ parse_and_run(File, Args, Options) ->
%% Parse script
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Only used as callback by erl_prim_loader
+parse_file(File) ->
+ try parse_file(File, false) of
+ {_Source, _Module, FormsOrBin, _HasRecs, _Mode}
+ when is_binary(FormsOrBin) ->
+ {ok, FormsOrBin};
+ _ ->
+ {error, no_archive_bin}
+ catch
+ throw:Reason ->
+ {error, Reason}
+ end.
+
parse_file(File, CheckOnly) ->
{HeaderSz, NextLineNo, Fd, Sections} =
parse_header(File, false),
diff --git a/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_main2.erl b/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_main2.erl
index de56579998..431a51b0e5 100644
--- a/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_main2.erl
+++ b/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_main2.erl
@@ -21,6 +21,8 @@
-export([main/1]).
+-include_lib("kernel/include/file.hrl").
+
-define(DUMMY, archive_script_dummy).
-define(DICT, archive_script_dict).
@@ -32,7 +34,7 @@ main(MainArgs) ->
io:format("dummy:~p\n",[[E || E <- ErlArgs, element(1, E) =:= ?DUMMY]]),
%% Start the applications
- {error, {not_started, ?DICT}} = application:start(archive_script_dummy),
+ {error, {not_started, ?DICT}} = application:start(?DUMMY),
ok = application:start(?DICT),
ok = application:start(?DUMMY),
@@ -57,4 +59,17 @@ main(MainArgs) ->
ok = ?DICT:erase(Tab, Key),
error = ?DICT:find(Tab, Key),
ok = ?DICT:erase(Tab),
+
+ %% Check mtime related caching bug with escript/primary archive files
+ Escript = escript:script_name(),
+ {ok, FileInfo} = file:read_file_info(Escript),
+ %% Modify mtime of archive file and try to reload module
+ FileInfo2 = FileInfo#file_info{mtime=calendar:now_to_local_time(now())},
+ ok = file:write_file_info(Escript, FileInfo2),
+ Module = ?DICT,
+ {file, _} = code:is_loaded(Module),
+ true = code:delete(Module),
+ false = code:is_loaded(Module),
+ {module, Module} = code:ensure_loaded(Module),
+
ok.