Skip to content

Commit c476bd9

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 c476bd9

File tree

1 file changed

+25
-14
lines changed

1 file changed

+25
-14
lines changed

apps/expert/lib/expert/engine_node.ex

Lines changed: 25 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,29 @@ 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+
code =
74+
quote do
75+
node = unquote(project_node)
76+
77+
# We start distribution here, rather than on node boot, so that
78+
# -pa takes effect and Forge.EPMD is available
79+
{:ok, _} = Node.start(node, :longnames)
80+
Forge.NodePortMapper.register()
81+
end
82+
83+
code
84+
|> Macro.to_string()
85+
|> Base.encode64()
86+
end
87+
7788
def stop(%__MODULE__{} = state, from, stop_timeout) do
7889
project_rpc(state, System, :stop)
7990
%{state | stopped_by: from, stop_timeout: stop_timeout, status: :stopping}

0 commit comments

Comments
 (0)