@@ -28,20 +28,39 @@ defmodule Expert.EngineNode do
2828 @ dialyzer { :nowarn_function , start: 3 }
2929
3030 def start ( % __MODULE__ { } = state , paths , from ) do
31- this_node = inspect ( Node . self ( ) )
32-
33- args = [
34- "--name" ,
35- Project . node_name ( state . project ) ,
36- "--cookie" ,
37- state . cookie ,
38- "--no-halt" ,
39- "-e" ,
40- "Node.connect(#{ this_node } )"
41- | path_append_arguments ( paths )
42- ]
43-
44- case Expert.Port . open_elixir ( state . project , args: args ) do
31+ this_node = to_string ( Node . self ( ) )
32+ dist_port = Forge.EPMD . dist_port ( )
33+
34+ args =
35+ [
36+ "--erl" ,
37+ "-start_epmd false -epmd_module #{ Forge.EPMD } " ,
38+ "--cookie" ,
39+ state . cookie ,
40+ "--no-halt" ,
41+ "-e" ,
42+ # We manually start distribution here instead of using --sname/--name
43+ # because those options are not really compatible with `-epmd_module`.
44+ # Apparently, passing the --name/-sname options causes the Erlang VM
45+ # to start distribution right away before the modules in the code path
46+ # are loaded, and it will crash because Forge.EPMD doesn't exist yet.
47+ # If we start distribution manually after all the code is loaded,
48+ # everything works fine.
49+ """
50+ {:ok, _} = Node.start(:"#{ Project . node_name ( state . project ) } ", :longnames)
51+ #{ Forge.NodePortMapper } .register()
52+ IO.puts(\" ok\" )
53+ """
54+ | path_append_arguments ( paths )
55+ ]
56+
57+ env =
58+ [
59+ { "EXPERT_PARENT_NODE" , this_node } ,
60+ { "EXPERT_PARENT_PORT" , to_string ( dist_port ) }
61+ ]
62+
63+ case Expert.Port . open_elixir ( state . project , args: args , env: env ) do
4564 { :error , :no_elixir , message } ->
4665 GenLSP . error ( Expert . get_lsp ( ) , message )
4766 Expert . terminate ( "Failed to find an elixir executable, shutting down" , 1 )
@@ -64,7 +83,7 @@ defmodule Expert.EngineNode do
6483 end
6584
6685 def on_nodeup ( % __MODULE__ { } = state , node_name ) do
67- if node_name == Project . node_name ( state . project ) do
86+ if String . starts_with? ( to_string ( node_name ) , to_string ( Project . node_name ( state . project ) ) ) do
6887 { pid , _ref } = state . started_by
6988 Process . monitor ( pid )
7089 GenServer . reply ( state . started_by , :ok )
@@ -117,7 +136,6 @@ defmodule Expert.EngineNode do
117136 use GenServer
118137
119138 def start ( project ) do
120- :ok = ensure_epmd_started ( )
121139 start_net_kernel ( project )
122140
123141 node_name = Project . node_name ( project )
@@ -134,23 +152,13 @@ defmodule Expert.EngineNode do
134152
135153 defp start_net_kernel ( % Project { } = project ) do
136154 manager = Project . manager_node_name ( project )
137- :net_kernel . start ( manager , % { name_domain: : longnames} )
155+ Node . start ( manager , : longnames)
138156 end
139157
140158 defp ensure_apps_started ( node ) do
141159 :rpc . call ( node , Engine , :ensure_apps_started , [ ] )
142160 end
143161
144- defp ensure_epmd_started do
145- case System . cmd ( "epmd" , ~w( -daemon) ) do
146- { "" , 0 } ->
147- :ok
148-
149- _ ->
150- { :error , :epmd_failed }
151- end
152- end
153-
154162 if Mix . env ( ) == :test do
155163 # In test environment, Expert depends on the Engine app, so we look for it
156164 # in the expert build path.
@@ -294,7 +302,7 @@ defmodule Expert.EngineNode do
294302
295303 @ impl true
296304 def handle_call ( { :start , paths } , from , % State { } = state ) do
297- :ok = :net_kernel . monitor_nodes ( true , node_type: :visible )
305+ :ok = :net_kernel . monitor_nodes ( true , node_type: :all )
298306 Process . send_after ( self ( ) , :maybe_start_timeout , @ start_timeout )
299307
300308 case State . start ( state , paths , from ) do
@@ -365,7 +373,8 @@ defmodule Expert.EngineNode do
365373 end
366374
367375 @ impl true
368- def handle_info ( { _port , { :data , _message } } , % State { } = state ) do
376+ def handle_info ( { _port , { :data , message } } , % State { } = state ) do
377+ Logger . debug ( "Node port message: #{ to_string ( message ) } " )
369378 { :noreply , state }
370379 end
371380
0 commit comments