From 787d00611f9808ada2096af2b58f5a944d2e0a53 Mon Sep 17 00:00:00 2001 From: Kornel Horvath Date: Thu, 21 Nov 2024 19:11:19 +0100 Subject: [PATCH] Use default shutdown time for gen_lsp_server Erlang/OTP `supervisor` documentation says: [1] > It is also allowed to set it to `infinity`, if the child process is a > worker. > > Warning > > Be careful when setting the shutdown time to `infinity` when the child > process is a worker. Because, in this situation, the termination of > the supervision tree depends on the child process, it must be > implemented in a safe way and its cleanup procedure must always > return. Therefore, the shutdown time of `gen_lsp_server` is changed from `infinity` to default value, that is `5000` milliseconds for worker processes. Additionally, a sketch of the application supervision tree is added to module header of `vscode_lsp_app` for easier understanding. The `-behaviour` attributes are added to the corresponding modules, also for easier understanding. [1] https://www.erlang.org/doc/man/supervisor.html --- .../src/gen_lsp_config_server.erl | 12 +++-- apps/erlangbridge/src/gen_lsp_config_sup.erl | 7 ++- apps/erlangbridge/src/gen_lsp_doc_server.erl | 6 ++- apps/erlangbridge/src/gen_lsp_doc_sup.erl | 7 ++- apps/erlangbridge/src/gen_lsp_help_server.erl | 6 ++- apps/erlangbridge/src/gen_lsp_help_sup.erl | 7 ++- apps/erlangbridge/src/gen_lsp_server.erl | 7 ++- apps/erlangbridge/src/gen_lsp_sup.erl | 13 +++-- apps/erlangbridge/src/vscode_lsp_app.erl | 53 +++++++++++++++---- apps/erlangbridge/src/vscode_lsp_app_sup.erl | 15 +++--- 10 files changed, 100 insertions(+), 33 deletions(-) diff --git a/apps/erlangbridge/src/gen_lsp_config_server.erl b/apps/erlangbridge/src/gen_lsp_config_server.erl index cfb9881..c9a53af 100644 --- a/apps/erlangbridge/src/gen_lsp_config_server.erl +++ b/apps/erlangbridge/src/gen_lsp_config_server.erl @@ -1,13 +1,15 @@ -module(gen_lsp_config_server). - -behavior(gen_server). --export([start_link/0]). --export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). +%% API +-export([start_link/0]). -export([standard_modules/0, bifs/0]). -export([update_config/2, root/0, tmpdir/0, codeLensEnabled/0, includePaths/0, linting/0, - verbose/0, autosave/0, proxy/0, search_files_exclude/0, search_exclude/0, - formatting_line_length/0, inlayHintsEnabled/0, verbose_is_include/1]). + verbose/0, autosave/0, proxy/0, search_files_exclude/0, search_exclude/0, + formatting_line_length/0, inlayHintsEnabled/0, verbose_is_include/1]). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -include("lsp_log.hrl"). -define(SERVER, ?MODULE). diff --git a/apps/erlangbridge/src/gen_lsp_config_sup.erl b/apps/erlangbridge/src/gen_lsp_config_sup.erl index 7dba86c..9d9538c 100644 --- a/apps/erlangbridge/src/gen_lsp_config_sup.erl +++ b/apps/erlangbridge/src/gen_lsp_config_sup.erl @@ -1,6 +1,11 @@ -module(gen_lsp_config_sup). +-behaviour(supervisor). --export([init/1, start_link/0]). +%% API +-export([start_link/0]). + +%% Supervisor callbacks +-export([init/1]). start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). diff --git a/apps/erlangbridge/src/gen_lsp_doc_server.erl b/apps/erlangbridge/src/gen_lsp_doc_server.erl index 740c370..c26a289 100644 --- a/apps/erlangbridge/src/gen_lsp_doc_server.erl +++ b/apps/erlangbridge/src/gen_lsp_doc_server.erl @@ -1,13 +1,17 @@ -module(gen_lsp_doc_server). - -behavior(gen_server). + +%% API -export([start_link/0]). -export([document_opened/2, document_changed/2, document_closed/1, opened_documents/0, get_document_contents/1, parse_document/1]). -export([project_file_added/1, project_file_changed/1, project_file_deleted/1]). -export([get_syntax_tree/1, get_dodged_syntax_tree/1, get_references/1, get_inlayhints/1]). -export([root_available/0, config_change/0, project_modules/0, get_module_file/1, get_module_files/1, get_build_dir/0, find_source_file/1]). + +%% gen_server callbacks -export([init/1,handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). + -include("./lsp_log.hrl"). -define(SERVER, ?MODULE). diff --git a/apps/erlangbridge/src/gen_lsp_doc_sup.erl b/apps/erlangbridge/src/gen_lsp_doc_sup.erl index 70dd424..3d85264 100644 --- a/apps/erlangbridge/src/gen_lsp_doc_sup.erl +++ b/apps/erlangbridge/src/gen_lsp_doc_sup.erl @@ -1,6 +1,11 @@ -module(gen_lsp_doc_sup). +-behaviour(supervisor). --export([init/1, start_link/0]). +%% API +-export([start_link/0]). + +%% Supervisor callbacks +-export([init/1]). start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). diff --git a/apps/erlangbridge/src/gen_lsp_help_server.erl b/apps/erlangbridge/src/gen_lsp_help_server.erl index 1811cd9..d880258 100644 --- a/apps/erlangbridge/src/gen_lsp_help_server.erl +++ b/apps/erlangbridge/src/gen_lsp_help_server.erl @@ -1,10 +1,12 @@ -module(gen_lsp_help_server). - -behavior(gen_server). + +%% API -export([start_link/0]). +-export([get_help/2,get_help/5, render_help_body/3]). +%% gen_server callbacks -export([init/1,handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). --export([get_help/2,get_help/5, render_help_body/3]). -define(SERVER, ?MODULE). diff --git a/apps/erlangbridge/src/gen_lsp_help_sup.erl b/apps/erlangbridge/src/gen_lsp_help_sup.erl index 2e48a98..b63e1b6 100644 --- a/apps/erlangbridge/src/gen_lsp_help_sup.erl +++ b/apps/erlangbridge/src/gen_lsp_help_sup.erl @@ -1,6 +1,11 @@ -module(gen_lsp_help_sup). +-behaviour(supervisor). --export([init/1, start_link/0]). +%% API +-export([start_link/0]). + +%% Supervisor callbacks +-export([init/1]). start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). diff --git a/apps/erlangbridge/src/gen_lsp_server.erl b/apps/erlangbridge/src/gen_lsp_server.erl index 09aa705..45d48a2 100644 --- a/apps/erlangbridge/src/gen_lsp_server.erl +++ b/apps/erlangbridge/src/gen_lsp_server.erl @@ -1,5 +1,4 @@ -module(gen_lsp_server). - -behavior(gen_server). %inspired from https://github.com/kevinlynx/erlang-tcpserver/blob/master/test/test.erl @@ -9,12 +8,12 @@ % http://learnyousomeerlang.com/buckets-of-sockets -%API +%% API -export([start_link/1, start_link/2]). +-export([lsp_log/2, send_to_client/2]). -%export for gen_server +%% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). --export([lsp_log/2, send_to_client/2]). -define(SERVER, ?MODULE). %state diff --git a/apps/erlangbridge/src/gen_lsp_sup.erl b/apps/erlangbridge/src/gen_lsp_sup.erl index b0aa0d1..d7b6c01 100644 --- a/apps/erlangbridge/src/gen_lsp_sup.erl +++ b/apps/erlangbridge/src/gen_lsp_sup.erl @@ -1,6 +1,10 @@ -module(gen_lsp_sup). +-behaviour(supervisor). +%% API -export([start_link/1]). + +%% Supervisor callbacks -export([init/1]). -define(TCP_OPTIONS, [binary, {packet, raw}, {active, once}, {reuseaddr, true}]). @@ -17,8 +21,11 @@ start_link(Port) -> init(VsCodePort) -> {ok, LSock} = gen_tcp:listen(list_to_integer(VsCodePort), ?TCP_OPTIONS), - UserSpec = {gen_lsp_server, {gen_lsp_server, start_link, [list_to_integer(VsCodePort), LSock]}, - temporary, infinity, worker, [gen_lsp_server]}, + UserSpec = #{id => gen_lsp_server, + start => {gen_lsp_server, start_link, [list_to_integer(VsCodePort), LSock]}, + restart => temporary, + modules => [gen_lsp_server], + type => worker}, StartSpecs = {{simple_one_for_one, 60, 3600}, [UserSpec]}, - gen_tcp:send(LSock, <<"{}">>), + gen_tcp:send(LSock, <<"{}">>), {ok, StartSpecs}. diff --git a/apps/erlangbridge/src/vscode_lsp_app.erl b/apps/erlangbridge/src/vscode_lsp_app.erl index db61189..5422369 100644 --- a/apps/erlangbridge/src/vscode_lsp_app.erl +++ b/apps/erlangbridge/src/vscode_lsp_app.erl @@ -1,16 +1,52 @@ +%%%------------------------------------------------------------------- +%%% @doc Erlang Language Server Process (LSP) for Visual Studio Code. +%%% +%%% Application supervision tree: +%%% +%%% ``` +%%% vscode_lsp_entry +%%% | +%%% | vscode_lsp [app.src] +%%% | +%%% vscode_lsp_app [app] +%%% | +%%% vscode_lsp_app_sup [sup] +%%% | +%%% +--gen_lsp_sup [sup] +%%% | | +%%% | +--gen_lsp_server [gen_server] +%%% | +%%% +--gen_lsp_doc_sup [sup] +%%% | | - (D)ETS document_contents +%%% | | - (D)ETS document_inlayhints +%%% | | - (D)ETS dodged_syntax_tree +%%% | | - ETS references +%%% | | - (D)ETS syntax_tree +%%% | | +%%% | +--gen_lsp_doc_server [gen_server] +%%% | +%%% +--gen_lsp_config_sup [sup] +%%% | | +%%% | +--gen_lsp_config_server [gen_server] +%%% | +%%% +--gen_lsp_help_sup [sup] +%%% | +%%% +--gen_lsp_help_server [gen_server] +%%% ''' +%%% +%%% @end +%%%------------------------------------------------------------------- -module(vscode_lsp_app). - -behavior(application). +%% Application callbacks -export([start/2, stop/1]). - get_port() -> case init:get_argument(vscode_port) of - {ok, [[P]]} -> P; - _ -> "0" + {ok, [[P]]} -> P; + _ -> "0" end. - start(_Type, _Args) -> application:start(inets), @@ -18,10 +54,9 @@ start(_Type, _Args) -> %spawn(fun() -> observer:start() end), Port = get_port(), case vscode_lsp_app_sup:start_link(Port) of - {ok, Pid} -> - {ok, Pid}; - _Any -> _Any + {ok, Pid} -> {ok, Pid}; + _Any -> _Any end. stop(_State) -> - ok. \ No newline at end of file + ok. diff --git a/apps/erlangbridge/src/vscode_lsp_app_sup.erl b/apps/erlangbridge/src/vscode_lsp_app_sup.erl index 9529365..1a5baad 100644 --- a/apps/erlangbridge/src/vscode_lsp_app_sup.erl +++ b/apps/erlangbridge/src/vscode_lsp_app_sup.erl @@ -1,6 +1,11 @@ -module(vscode_lsp_app_sup). +-behaviour(supervisor). --export([init/1, start_link/1, start_sup_socket/1, start_sup_doc/0, start_sup_config/0, start_sup_help/0, start_child/1]). +%% API +-export([start_link/1, start_sup_socket/1, start_sup_doc/0, start_sup_config/0, start_sup_help/0, start_child/1]). + +%% Supervisor callbacks +-export([init/1]). start_link(VsCodePort) -> supervisor:start_link({local, ?MODULE}, ?MODULE, VsCodePort). @@ -20,17 +25,12 @@ socket_spec(VsCodePort) -> modules => [gen_lsp_sup], type => supervisor}. -start_sup_socket(VsCodePort) -> - supervisor:start_child({local, ?MODULE}, socket_spec(VsCodePort)). - doc_spec() -> #{id => gen_lsp_doc_sup, start => {gen_lsp_doc_sup, start_link, []}, restart => permanent, modules => [gen_lsp_doc_sup], type => supervisor}. -% {gen_lsp_doc_sup, {gen_lsp_doc_sup, start_link, []}, -% permanent, infinity, supervisor, [gen_lsp_doc_sup]}. config_spec() -> #{id => gen_lsp_config_sup, @@ -46,6 +46,9 @@ help_spec() -> modules => [gen_lsp_help_sup], type => supervisor}. +start_sup_socket(VsCodePort) -> + supervisor:start_child({local, ?MODULE}, socket_spec(VsCodePort)). + start_sup_doc() -> supervisor:start_child(?MODULE, doc_spec()).