Skip to content

Commit 3b99b09

Browse files
committed
refactor: use quote + base64 to pass eval string
This is the same method Livebook uses for the very same reasons
1 parent 8bc2d77 commit 3b99b09

File tree

1 file changed

+22
-14
lines changed

1 file changed

+22
-14
lines changed

apps/expert/lib/expert/engine_node.ex

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,20 +40,8 @@ defmodule Expert.EngineNode do
4040
state.cookie,
4141
"--no-halt",
4242
"-e",
43-
# We manually start distribution here instead of using --sname/--name
44-
# because those options are not really compatible with `-epmd_module`.
45-
# Apparently, passing the --name/-sname options causes the Erlang VM
46-
# to start distribution right away before the modules in the code path
47-
# are loaded, and it will crash because Forge.EPMD doesn't exist yet.
48-
# If we start distribution manually after all the code is loaded,
49-
# everything works fine.
50-
# We also need to pass the command as a single line with ;\, otherwise
51-
# this will only run the first line on Windows.
52-
"""
53-
{:ok, _} = Node.start(:"#{Project.node_name(state.project)}", :longnames);\
54-
#{Forge.NodePortMapper}.register();\
55-
IO.puts(\"ok\");\
56-
"""
43+
"System.argv() |> hd() |> Base.decode64!() |> Code.eval_string()",
44+
project_node_eval_string(state.project)
5745
]
5846

5947
env =
@@ -74,6 +62,26 @@ defmodule Expert.EngineNode do
7462
end
7563
end
7664

65+
defp project_node_eval_string(project) do
66+
# We pass the child node code as --eval argument. Windows handles
67+
# escaped quotes and newlines differently from Unix, so to avoid
68+
# those kind of issues, we encode the string in base 64 and pass
69+
# as positional argument. Then, we use a simple --eval that decodes
70+
# and evaluates the string.
71+
project_node = Project.node_name(project)
72+
73+
quote do
74+
node = unquote(project_node)
75+
76+
# We start distribution here, rather than on node boot, so that
77+
# -pa takes effect and Forge.EPMD is available
78+
{:ok, _} = Node.start(node, :longnames)
79+
Forge.NodePortMapper.register()
80+
end
81+
|> Macro.to_string()
82+
|> Base.encode64()
83+
end
84+
7785
def stop(%__MODULE__{} = state, from, stop_timeout) do
7886
project_rpc(state, System, :stop)
7987
%{state | stopped_by: from, stop_timeout: stop_timeout, status: :stopping}

0 commit comments

Comments
 (0)