Class: MilkTea::DAP::Backends::LLDBDAP
- Inherits:
-
Object
- Object
- MilkTea::DAP::Backends::LLDBDAP
- Defined in:
- lib/milk_tea/dap/backends/lldb_dap.rb
Overview
Thin bridge to an lldb-dap compatible adapter process.
Instance Method Summary collapse
- #drain_stderr ⇒ Object
- #handle_adapter_request(message) ⇒ Object
-
#initialize(adapter_command: ["lldb-dap"], on_event: nil, on_request: nil) ⇒ LLDBDAP
constructor
A new instance of LLDBDAP.
- #next_seq ⇒ Object
- #read_loop ⇒ Object
- #request(command, arguments = {}, timeout: 5) ⇒ Object
- #running? ⇒ Boolean
- #start! ⇒ Object
- #stop! ⇒ Object
Constructor Details
#initialize(adapter_command: ["lldb-dap"], on_event: nil, on_request: nil) ⇒ LLDBDAP
Returns a new instance of LLDBDAP.
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
# File 'lib/milk_tea/dap/backends/lldb_dap.rb', line 12 def initialize(adapter_command: ["lldb-dap"], on_event: nil, on_request: nil) @adapter_command = adapter_command @on_event = on_event @on_request = on_request @protocol = nil @stdin = nil @stdout = nil @stderr = nil @wait_thread = nil @reader_thread = nil @stderr_thread = nil @write_mutex = Mutex.new @pending_mutex = Mutex.new @pending = {} @next_seq = 1 end |
Instance Method Details
#drain_stderr ⇒ Object
129 130 131 132 133 134 135 136 137 |
# File 'lib/milk_tea/dap/backends/lldb_dap.rb', line 129 def drain_stderr return unless @stderr @stderr.each_line do |_line| # Intentionally ignored in this bridge layer. end rescue StandardError nil end |
#handle_adapter_request(message) ⇒ Object
139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/milk_tea/dap/backends/lldb_dap.rb', line 139 def handle_adapter_request() response = @on_request&.call() response ||= { "type" => "response", "request_seq" => ["seq"], "success" => false, "command" => ["command"], "message" => "unsupported reverse request: #{['command']}" } @write_mutex.synchronize do @protocol.(response) end end |
#next_seq ⇒ Object
94 95 96 97 98 |
# File 'lib/milk_tea/dap/backends/lldb_dap.rb', line 94 def next_seq seq = @next_seq @next_seq += 1 seq end |
#read_loop ⇒ Object
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/milk_tea/dap/backends/lldb_dap.rb', line 100 def read_loop loop do = @protocol. break if .nil? if ["type"] == "response" queue = @pending_mutex.synchronize { @pending[["request_seq"]] } queue&.push() elsif ["type"] == "event" @on_event&.call() elsif ["type"] == "request" handle_adapter_request() end end rescue StandardError nil ensure @pending_mutex.synchronize do @pending.each_value do |queue| queue.push({ "type" => "response", "success" => false, "message" => "backend closed" }) end @pending.clear end end |
#request(command, arguments = {}, timeout: 5) ⇒ Object
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/milk_tea/dap/backends/lldb_dap.rb', line 43 def request(command, arguments = {}, timeout: 5) start! unless running? seq = next_seq queue = Queue.new @pending_mutex.synchronize do @pending[seq] = queue end @write_mutex.synchronize do @protocol.({ seq: seq, type: "request", command: command, arguments: arguments }) end Timeout.timeout(timeout) { queue.pop } rescue Timeout::Error { "type" => "response", "request_seq" => seq, "success" => false, "message" => "backend request timed out: #{command}" } ensure @pending_mutex.synchronize { @pending.delete(seq) } end |
#running? ⇒ Boolean
39 40 41 |
# File 'lib/milk_tea/dap/backends/lldb_dap.rb', line 39 def running? !@wait_thread.nil? && @wait_thread.alive? end |
#start! ⇒ Object
29 30 31 32 33 34 35 36 37 |
# File 'lib/milk_tea/dap/backends/lldb_dap.rb', line 29 def start! return if running? @stdin, @stdout, @stderr, @wait_thread = Open3.popen3(*@adapter_command) @protocol = Protocol.new(input: @stdout, output: @stdin) @reader_thread = Thread.new { read_loop } @stderr_thread = Thread.new { drain_stderr } end |
#stop! ⇒ Object
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/milk_tea/dap/backends/lldb_dap.rb', line 73 def stop! @stdin&.close @stdout&.close @stderr&.close if @wait_thread&.alive? Process.kill("TERM", @wait_thread.pid) end rescue StandardError nil ensure @wait_thread&.join(0.2) @reader_thread&.join(0.2) @stderr_thread&.join(0.2) @stdin = nil @stdout = nil @stderr = nil @wait_thread = nil @reader_thread = nil @stderr_thread = nil end |