Skip to content

Commit ce9ac22

Browse files
niklasdoorgan
andauthored
fix(engine): handle failing build script (#188)
* Handle failing build script When the build script fails for some reason, the EngineNode hung, because the :EXIT would not be received, as the Port was started in some other process, but not in the EngineNode's GenServer. Only the latter explicitely traps exits. To fix this without causing any side effects (handle_info(:EXIT) in Node), we run the Port in a Task subprocess that traps exits. Additionally, we log the last line received from the build script to help the user to debug the issue, instead of failing silently with exit reason :normal. * fix: add debug logs for project engine build * refactor: start pipe with raw value --------- Co-authored-by: doorgan <[email protected]>
1 parent 25f80c8 commit ce9ac22

File tree

2 files changed

+16
-13
lines changed

2 files changed

+16
-13
lines changed

apps/expert/lib/expert/engine_node.ex

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -215,13 +215,15 @@ defmodule Expert.EngineNode do
215215
GenLSP.info(lsp, "Finding or building engine for project #{project_name}")
216216

217217
with_progress(project, "Building engine for #{project_name}", fn ->
218-
port =
219-
Port.open(
220-
{:spawn_executable, launcher},
221-
opts
222-
)
223-
224-
wait_for_engine(port)
218+
fn ->
219+
Process.flag(:trap_exit, true)
220+
221+
{:spawn_executable, launcher}
222+
|> Port.open(opts)
223+
|> wait_for_engine()
224+
end
225+
|> Task.async()
226+
|> Task.await(:infinity)
225227
end)
226228

227229
{:error, :no_elixir, message} ->
@@ -230,20 +232,21 @@ defmodule Expert.EngineNode do
230232
end
231233
end
232234

233-
defp wait_for_engine(port) do
235+
defp wait_for_engine(port, last_line \\ "") do
234236
receive do
235237
{^port, {:data, ~c"engine_path:" ++ engine_path}} ->
236238
engine_path = engine_path |> to_string() |> String.trim()
237239
Logger.info("Engine build available at: #{engine_path}")
238240

239241
{:ok, ebin_paths(engine_path)}
240242

241-
{^port, _data} ->
242-
wait_for_engine(port)
243+
{^port, {:data, data}} ->
244+
Logger.debug("Building engine: #{to_string(data)}")
245+
wait_for_engine(port, data)
243246

244247
{:EXIT, ^port, reason} ->
245-
Logger.error("Engine build script exited with reason: #{inspect(reason)}")
246-
{:error, reason}
248+
Logger.error("Engine build script exited with reason: #{inspect(reason)} #{last_line}")
249+
{:error, reason, last_line}
247250
end
248251
end
249252

apps/expert/lib/expert/state.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ defmodule Expert.State do
5656
response = initialize_result()
5757

5858
Task.Supervisor.start_child(:expert_task_queue, fn ->
59-
Project.Supervisor.start(config.project)
59+
{:ok, _pid} = Project.Supervisor.start(config.project)
6060
send(Expert, :engine_initialized)
6161
end)
6262

0 commit comments

Comments
 (0)