Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:26
erlang
2331-Check-for-embedded-mode-in-the-client.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 2331-Check-for-embedded-mode-in-the-client.patch of Package erlang
From e0ea6f5fd2b0a92e4ff8516c2a6f2680b31684fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= <jose.valim@dashbit.co> Date: Tue, 9 Jan 2024 11:44:52 +0100 Subject: [PATCH] Check for embedded mode in the client This ensures that checking for code:ensure_loaded/1 in embedded mode (and other operations) do not send additional messages to the code server. This pull request fully closes #7889. While previous work has fixed the slow path in the code server, this pull request makes it so the code server is avoided altogether. --- lib/kernel/doc/src/code.xml | 11 +++++++--- lib/kernel/src/code.erl | 29 ++++++++++++++----------- lib/kernel/src/code_server.erl | 39 +++++++++++++--------------------- 3 files changed, 40 insertions(+), 39 deletions(-) diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml index 66090cc6fd..7d5f2c10c9 100644 --- a/lib/kernel/doc/src/code.xml +++ b/lib/kernel/doc/src/code.xml @@ -602,8 +602,11 @@ ok = code:finish_loading(Prepared), <desc> <p>Tries to load a module in the same way as <seemfa marker="#load_file/1"><c>load_file/1</c></seemfa>, - unless the module is already loaded. - However, in embedded mode it does not load a module that is not + unless the module is already loaded. If called concurrently, + this function ensures only one process attempts to load said + module at a given time.</p> + + <p>In embedded mode, it does not load a module that is not already loaded, but returns <c>{error, embedded}</c> instead. See <seeerl marker="#error_reasons">Error Reasons for Code-Loading Functions</seeerl> for a description of other possible error reasons.</p> </desc> @@ -614,7 +617,9 @@ ok = code:finish_loading(Prepared), <desc> <p>Tries to load any modules not already loaded in the list <c><anno>Modules</anno></c> in the same way as - <seemfa marker="#load_file/1">load_file/1</seemfa>.</p> + <seemfa marker="#load_file/1">load_file/1</seemfa>. + Unlike <seemfa marker="#ensure_loaded/1">ensure_loaded/1</seemfa>, + modules are loaded even in <c>embedded</c> mode.</p> <p>Returns <c>ok</c> if successful, or <c>{error,[{Module,Reason}]}</c> if loading of some modules fails. See <seeerl marker="#error_reasons">Error Reasons for Code-Loading Functions</seeerl> for a description of other possible error reasons.</p> diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl index 7b82b6be9a..32555971dc 100644 --- a/lib/kernel/src/code.erl +++ b/lib/kernel/src/code.erl @@ -196,16 +196,21 @@ ensure_loaded(Mod) when is_atom(Mod) -> case erlang:module_loaded(Mod) of true -> {module, Mod}; false -> - case call({get_object_code_for_loading, Mod}) of - {module, Mod} -> {module, Mod}; - {error, What} -> {error, What}; - {Binary,File,Ref} -> - case ensure_prepare_loading(Mod, Binary, File) of - {error,_}=Error -> - call({load_error, Ref, Mod, Error}); - Prepared -> - call({load_module, Prepared, Mod, File, false, Ref}) - end + case get_mode() of + interactive -> + case call({get_object_code_for_loading, Mod}) of + {module, Mod} -> {module, Mod}; + {error, What} -> {error, What}; + {Binary,File,Ref} -> + case ensure_prepare_loading(Mod, Binary, File) of + {error,_}=Error -> + call({load_error, Ref, Mod, Error}); + Prepared -> + call({load_module, Prepared, Mod, File, false, Ref}) + end + end; + embedded -> + {error, embedded} end end. @@ -313,7 +318,7 @@ all_loaded() -> call(all_loaded). Filename :: loaded_filename(), Loaded :: boolean(). all_available() -> - case code:get_mode() of + case get_mode() of interactive -> all_available(get_path(), #{}); embedded -> @@ -520,7 +525,7 @@ replace_path(Name, Dir, Cache) when (is_atom(Name) orelse is_list(Name)), call({replace_path,Name,Dir,Cache}). -spec get_mode() -> 'embedded' | 'interactive'. -get_mode() -> call(get_mode). +get_mode() -> code_server:get_mode(). -spec clear_cache() -> ok. clear_cache() -> call(clear_cache). diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl index 5315fa1e1a..78e635a1a9 100644 --- a/lib/kernel/src/code_server.erl +++ b/lib/kernel/src/code_server.erl @@ -22,7 +22,7 @@ %% This file holds the server part of the code_server. -export([start_link/1, - call/1, absname/1, + call/1, absname/1, get_mode/0, is_loaded/1, is_sticky/1, system_code_change/4, error_msg/2, info_msg/2 @@ -46,7 +46,6 @@ path :: [{file:name_all(), cache | nocache}], moddb :: ets:table(), namedb :: ets:table(), - mode = interactive :: 'interactive' | 'embedded', on_load = [] :: [on_load_item()], loading = #{} :: #{module() => [pid()]}}). -type state() :: #state{}. @@ -70,6 +69,9 @@ is_loaded(Mod) -> is_sticky(Mod) -> is_sticky(Mod, ?moddb). +get_mode() -> + persistent_term:get(?MODULE). + %% ----------------------------------------------------------- %% Init the code_server process. %% ----------------------------------------------------------- @@ -104,9 +106,9 @@ init(Ref, Parent, [Root,Mode]) -> root = Root, path = Path, moddb = Db, - namedb = create_namedb(Path, Root), - mode = Mode}, + namedb = create_namedb(Path, Root)}, + persistent_term:put(?MODULE, Mode), Parent ! {Ref,{ok,self()}}, loop(State). @@ -342,7 +344,7 @@ handle_call({get_object_code,Mod}, _From, St0) when is_atom(Mod) -> handle_call({get_object_code_for_loading,Mod}, From, St0) when is_atom(Mod) -> case erlang:module_loaded(Mod) of true -> {reply, {module, Mod}, St0}; - false when St0#state.mode =:= interactive -> + false -> %% Handles pending on_load events first. If the code is being %% loaded, finish before adding more entries to the queue. Action = fun(_, St1) -> @@ -351,16 +353,12 @@ handle_call({get_object_code_for_loading,Mod}, From, St0) when is_atom(Mod) -> false -> get_object_code_for_loading(St1, Mod, From) end end, - handle_pending_on_load(Action, Mod, From, St0); - false -> {reply, {error,embedded}, St0} + handle_pending_on_load(Action, Mod, From, St0) end; handle_call(stop,_From, S) -> {stop,normal,stopped,S}; -handle_call(get_mode, _From, S=#state{mode=Mode}) -> - {reply, Mode, S}; - handle_call({finish_loading,Prepared,EnsureLoaded}, _From, S) -> {reply,finish_loading(Prepared, EnsureLoaded, S),S}; @@ -1087,20 +1085,13 @@ del_paths(_,Path,_) -> {ok,Path}. try_finish_module(File, Mod, PC, EnsureLoaded, From, St) -> - Action = case EnsureLoaded of - false -> - fun(_, S) -> try_finish_module_1(File, Mod, PC, From, false, S) end; - _ -> - fun(_, S0) -> - case erlang:module_loaded(Mod) of - true -> - reply_loading(EnsureLoaded, Mod, {module, Mod}, S0); - false when S0#state.mode =:= interactive -> - try_finish_module_1(File, Mod, PC, From, EnsureLoaded, S0); - false -> - reply_loading(EnsureLoaded, Mod, {error, embedded}, S0) - end - end + Action = fun(_, S) -> + case (EnsureLoaded =/= false) andalso erlang:module_loaded(Mod) of + true -> + reply_loading(EnsureLoaded, Mod, {module, Mod}, S); + false -> + try_finish_module_1(File, Mod, PC, From, EnsureLoaded, S) + end end, handle_pending_on_load(Action, Mod, From, St). -- 2.35.3
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor