File 3662-ensure_loaded-should-check-with-code-server-for-pend.patch of Package erlang
From c9e6925c2ebef688f682f07e87c0ea025648b658 Mon Sep 17 00:00:00 2001
From: frazze-jobb <frazze@erlang.org>
Date: Wed, 8 Feb 2023 06:47:18 +0100
Subject: [PATCH 2/2] ensure_loaded should check with code server, for pending
on_load
---
lib/kernel/src/code.erl | 19 +++++----
lib/kernel/src/code_server.erl | 71 +++++++++++++++-------------------
2 files changed, 44 insertions(+), 46 deletions(-)
diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl
index c56bbab4e5..932b48f300 100644
--- a/lib/kernel/src/code.erl
+++ b/lib/kernel/src/code.erl
@@ -186,7 +186,7 @@ objfile_extension() ->
load_file(Mod) when is_atom(Mod) ->
case get_object_code(Mod) of
error -> {error,nofile};
- {Mod,Binary,File} -> load_module(Mod, File, Binary, false)
+ {Mod,Binary,File} -> load_module(Mod, File, Binary, false, false)
end.
-spec ensure_loaded(Module) -> {module, Module} | {error, What} when
@@ -195,7 +195,12 @@ load_file(Mod) when is_atom(Mod) ->
ensure_loaded(Mod) when is_atom(Mod) ->
case erlang:module_loaded(Mod) of
true -> {module, Mod};
- false -> call({ensure_loaded,Mod})
+ false ->
+ case get_object_code(Mod) of
+ error -> call({sync_ensure_on_load, Mod});
+ {Mod,Binary,File} ->
+ load_module(Mod, File, Binary, false, true)
+ end
end.
%% XXX File as an atom is allowed only for backwards compatibility.
@@ -213,7 +218,7 @@ load_abs(File, M) when (is_list(File) orelse is_atom(File)), is_atom(M) ->
FileName = code_server:absname(FileName0),
case erl_prim_loader:get_file(FileName) of
{ok,Bin,_} ->
- load_module(M, FileName, Bin, false);
+ load_module(M, FileName, Bin, false, false);
error ->
{error, nofile}
end;
@@ -231,16 +236,16 @@ load_abs(File, M) when (is_list(File) orelse is_atom(File)), is_atom(M) ->
load_binary(Mod, File, Bin)
when is_atom(Mod), (is_list(File) orelse is_atom(File)), is_binary(Bin) ->
case modp(File) of
- true -> load_module(Mod, File, Bin, true);
+ true -> load_module(Mod, File, Bin, true, false);
false -> {error,badarg}
end.
-load_module(Mod, File, Bin, Purge) ->
+load_module(Mod, File, Bin, Purge, EnsureLoaded) ->
case erlang:prepare_loading(Mod, Bin) of
{error,_}=Error ->
Error;
Prepared ->
- call({load_module, Prepared, Mod, File, Purge})
+ call({load_module, Prepared, Mod, File, Purge, EnsureLoaded})
end.
modp(Atom) when is_atom(Atom) -> true;
@@ -1183,4 +1188,4 @@ path_files([Path|Tail]) ->
[{Path,Files} | path_files(Tail)];
_Error ->
path_files(Tail)
- end.
+ end.
\ No newline at end of file
diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl
index 8f0f9fba66..b9d4ae7022 100644
--- a/lib/kernel/src/code_server.erl
+++ b/lib/kernel/src/code_server.erl
@@ -289,22 +289,13 @@ handle_call({replace_path,Name,Dir}, _From,
handle_call(get_path, _From, S) ->
{reply,S#state.path,S};
-handle_call({load_module,PC,Mod,File,Purge}, From, S) when is_atom(Mod) ->
+handle_call({load_module,PC,Mod,File,Purge,EnsureLoaded}, From, S)
+ when is_atom(Mod) ->
case Purge andalso erlang:module_loaded(Mod) of
true -> do_purge(Mod);
false -> ok
end,
- try_finish_module(File, Mod, PC, From, S);
-
-handle_call({ensure_loaded,Mod}, From, St) when is_atom(Mod) ->
- case erlang:module_loaded(Mod) of
- true ->
- {reply,{module,Mod},St};
- false when St#state.mode =:= interactive ->
- ensure_loaded(Mod, From, St);
- false ->
- {reply,{error,embedded},St}
- end;
+ try_finish_module(File, Mod, PC, EnsureLoaded, From, S);
handle_call({delete,Mod}, _From, St) when is_atom(Mod) ->
case catch erlang:delete_module(Mod) of
@@ -350,6 +341,20 @@ handle_call(get_mode, _From, S=#state{mode=Mode}) ->
handle_call({finish_loading,Prepared,EnsureLoaded}, _From, S) ->
{reply,finish_loading(Prepared, EnsureLoaded, S),S};
+%% Handles pending on_load events when we cannot find any
+%% object code in code:ensure_loaded/1. It's possible that
+%% the user has loaded a binary that has an on_load
+%% function, and in that case we need to suspend them until
+%% the on_load function finishes.
+handle_call({sync_ensure_on_load, Mod}, From, S) ->
+ handle_pending_on_load(
+ fun(_, St) ->
+ case erlang:module_loaded(Mod) of
+ true -> {reply, {module, Mod}, St};
+ false -> {reply, {error, nofile}, St}
+ end
+ end, Mod, From, S);
+
handle_call(Other,_From, S) ->
error_msg(" ** Codeserver*** ignoring ~w~n ",[Other]),
{noreply,S}.
@@ -1077,9 +1082,21 @@ add_paths(Where,[Dir|Tail],Path,NameDb) ->
add_paths(_,_,Path,_) ->
{ok,Path}.
-try_finish_module(File, Mod, PC, From, St) ->
+try_finish_module(File, Mod, PC, true, From, St) ->
+ Action = fun(_, S) ->
+ case erlang:module_loaded(Mod) of
+ true ->
+ {reply,{module,Mod},S};
+ false when S#state.mode =:= interactive ->
+ try_finish_module_1(File, Mod, PC, From, S);
+ false ->
+ {reply,{error,embedded},S}
+ end
+ end,
+ handle_pending_on_load(Action, Mod, From, St);
+try_finish_module(File, Mod, PC, false, From, St) ->
Action = fun(_, S) ->
- try_finish_module_1(File, Mod, PC, From, S)
+ try_finish_module_1(File, Mod, PC, From, S)
end,
handle_pending_on_load(Action, Mod, From, St).
@@ -1114,30 +1131,6 @@ int_list([H|T]) when is_integer(H) -> int_list(T);
int_list([_|_]) -> false;
int_list([]) -> true.
-ensure_loaded(Mod, From, St0) ->
- Action = fun(_, S) ->
- case erlang:module_loaded(Mod) of
- true ->
- {reply,{module,Mod},S};
- false ->
- ensure_loaded_1(Mod, From, S)
- end
- end,
- handle_pending_on_load(Action, Mod, From, St0).
-
-ensure_loaded_1(Mod, From, St) ->
- case get_object_code(St, Mod) of
- error ->
- {reply,{error,nofile},St};
- {Mod,Binary,File} ->
- case erlang:prepare_loading(Mod, Binary) of
- {error, _} = Error ->
- {reply, Error, St};
- PC ->
- try_finish_module_1(File, Mod, PC, From, St)
- end
- end.
-
get_object_code(#state{path=Path}, Mod) when is_atom(Mod) ->
ModStr = atom_to_list(Mod),
case erl_prim_loader:is_basename(ModStr) of
@@ -1410,4 +1403,4 @@ archive_extension() ->
init:archive_extension().
to_list(X) when is_list(X) -> X;
-to_list(X) when is_atom(X) -> atom_to_list(X).
+to_list(X) when is_atom(X) -> atom_to_list(X).
\ No newline at end of file
--
2.35.3