Skip to content

Commit

Permalink
Improve debugger stability (#457)
Browse files Browse the repository at this point in the history
* remove legacy io_request handlers

we don't support OTP < R15B

* rescue MatchError in :int calls

Fixes #455

* make output device better conform to erlang I/O protocol

see https://erlang.org/doc/apps/stdlib/io_protocol.html for details

* return WireProtocol.send error to the caller

no need to IO.warn if write fails

* we are redirection stderr to stdout, use stdout as underlying device

* inspect error

* monitor debugged processes

add test for mix task exit
Fixes #454

* avoid debugger crashes when handling requests for no longer existing thread, frame and variable ids

Fixes #452

* add test

* forbid changes of underlying device opts

* refactor and add tests coverage to invalid requests

* Map.pop! is available since elixir 1.10

* run formatter
  • Loading branch information
lukaszsamson committed Jan 14, 2021
1 parent e8c381b commit 4ae6e22
Show file tree
Hide file tree
Showing 10 changed files with 992 additions and 188 deletions.
1 change: 1 addition & 0 deletions apps/elixir_ls_debugger/lib/debugger/cli.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ defmodule ElixirLS.Debugger.CLI do
WireProtocol.intercept_output(&Output.print/1, &Output.print_err/1)
Launch.start_mix()
{:ok, _} = Application.ensure_all_started(:elixir_ls_debugger, :permanent)

IO.puts("Started ElixirLS debugger v#{Launch.debugger_version()}")
Launch.print_versions()
Launch.limit_num_schedulers()
Expand Down
39 changes: 20 additions & 19 deletions apps/elixir_ls_debugger/lib/debugger/output.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ defmodule ElixirLS.Debugger.Output do
are sent with sequence numbers that are unique and sequential, and includes client functions for
sending these messages.
"""
import ElixirLS.Utils.WireProtocol, only: [send: 1]
alias ElixirLS.Utils.WireProtocol
use GenServer
use ElixirLS.Debugger.Protocol

Expand All @@ -29,12 +29,12 @@ defmodule ElixirLS.Debugger.Output do
GenServer.call(server, {:send_event, event, body})
end

def print(server \\ __MODULE__, str) do
send_event(server, "output", %{"category" => "stdout", "output" => to_string(str)})
def print(server \\ __MODULE__, str) when is_binary(str) do
send_event(server, "output", %{"category" => "stdout", "output" => str})
end

def print_err(server \\ __MODULE__, str) do
send_event(server, "output", %{"category" => "stderr", "output" => to_string(str)})
def print_err(server \\ __MODULE__, str) when is_binary(str) do
send_event(server, "output", %{"category" => "stderr", "output" => str})
end

## Server callbacks
Expand All @@ -46,27 +46,28 @@ defmodule ElixirLS.Debugger.Output do

@impl GenServer
def handle_call({:send_response, request_packet, body}, _from, seq) do
send(response(seq, request_packet["seq"], request_packet["command"], body))
{:reply, :ok, seq + 1}
res = WireProtocol.send(response(seq, request_packet["seq"], request_packet["command"], body))
{:reply, res, seq + 1}
end

def handle_call({:send_error_response, request_packet, message, format, variables}, _from, seq) do
send(
error_response(
seq,
request_packet["seq"],
request_packet["command"],
message,
format,
variables
res =
WireProtocol.send(
error_response(
seq,
request_packet["seq"],
request_packet["command"],
message,
format,
variables
)
)
)

{:reply, :ok, seq + 1}
{:reply, res, seq + 1}
end

def handle_call({:send_event, event, body}, _from, seq) do
send(event(seq, event, body))
{:reply, :ok, seq + 1}
res = WireProtocol.send(event(seq, event, body))
{:reply, res, seq + 1}
end
end
Loading

0 comments on commit 4ae6e22

Please sign in to comment.