Class: MilkTea::DAP::Server

Inherits:
Object
  • Object
show all
Includes:
ServerBreakpoints, ServerDebugMap, ServerHandlers, ServerLLDBBackend, ServerLaunch, ServerPauseDiagnostics, ServerUtilities, ServerWire
Defined in:
lib/milk_tea/dap/server.rb,
lib/milk_tea/dap/server/wire.rb,
lib/milk_tea/dap/server/launch.rb,
lib/milk_tea/dap/server/handlers.rb,
lib/milk_tea/dap/server/debug_map.rb,
lib/milk_tea/dap/server/utilities.rb,
lib/milk_tea/dap/server/breakpoints.rb,
lib/milk_tea/dap/server/lldb_backend.rb,
lib/milk_tea/dap/server/pause_diagnostics.rb

Overview

Minimal DAP server with strict request/response/event envelopes.

Defined Under Namespace

Modules: ServerBreakpoints, ServerDebugMap, ServerHandlers, ServerLLDBBackend, ServerLaunch, ServerPauseDiagnostics, ServerUtilities, ServerWire

Constant Summary collapse

ADAPTER_CAPABILITIES =
{
  supportsConfigurationDoneRequest: true,
  supportsFunctionBreakpoints: true,
  supportsConditionalBreakpoints: false,
  supportsHitConditionalBreakpoints: false,
  supportsPauseRequest: true,
  supportsEvaluateForHovers: false,
  supportsSetVariable: false,
  supportsTerminateRequest: true,
  supportTerminateDebuggee: true,
  supportsLoadedSourcesRequest: true,
  exceptionBreakpointFilters: [],
}.freeze

Constants included from ServerUtilities

ServerUtilities::PERF_LOG_THRESHOLD_MS

Instance Method Summary collapse

Methods included from ServerUtilities

#cleanup_tmp_dirs, #dap_perf_logging?, #dap_perf_verbose?, #dap_set, #dap_value, #join_background_threads, #normalize_reference_key, #process_message, #register_handlers, #summarize_dap_arguments, #track_background_thread

Methods included from ServerWire

#write_error_response, #write_event, #write_message, #write_response

Methods included from ServerPauseDiagnostics

#emit_pause_diagnostic_async, #informative_pause_frame?, #pause_diagnostic_output, #pause_frame_summary

Methods included from ServerBreakpoints

#sync_breakpoints_to_backend, #sync_exception_breakpoints_to_backend, #sync_function_breakpoints_to_backend

Methods included from ServerDebugMap

#accessor_identifier?, #clear_debug_context, #copy_quoted_segment, #debug_function_for_frame, #debug_function_for_variables_reference, #identifier_continue_char?, #identifier_start_char?, #load_debug_map, #maybe_load_debug_map_from_backend_modules, #request_set_variable, #rewrite_data_breakpoint_info_arguments, #rewrite_evaluate_arguments, #rewrite_expression_for_frame, #rewrite_expression_for_function, #rewrite_scopes_response, #rewrite_set_expression_arguments, #rewrite_set_variable_arguments, #rewrite_stack_trace_response, #rewrite_variables_response, #variables_reference_context, #whitespace_char?

Methods included from ServerLLDBBackend

#backend_configuration_pending?, #backend_configuration_ready?, #backend_continue_arguments, #backend_error_message, #backend_initialize_arguments, #backend_request, #backend_start_pending?, #backend_supports_set_expression?, #backend_supports_set_variable?, #backend_terminate_unsupported?, #backend_thread_id_for_auto_continue, #build_backend_request_response, #build_backend_via_factory, #capability_enabled?, #continued_event_signature, #effective_adapter_capabilities, #ensure_backend_initialized, #filter_breakpoint_for_backend, #handle_backend_event, #handle_backend_request, #handle_client_response, #mark_backend_configuration_ready, #request_backend_terminate, #reset_backend_configuration_ready, #reverse_request_timeout, #rewrite_backend_stopped_event_body, #start_backend_start_request, #start_lldb_backend, #stop_lldb_backend, #using_lldb_backend?, #wait_for_backend_configuration_ready, #write_backend_response

Methods included from ServerLaunch

#backend_start_arguments, #continue_runtime_if_paused, #default_backend_kind, #maybe_start_or_stop_on_entry, #pause_runtime_if_running, #request_start, #resolve_debug_program, #resolve_launch_program, #resolved_backend_kind, #start_runtime_if_needed, #terminate_runtime_if_running, #write_stopped

Methods included from ServerHandlers

#handle_attach, #handle_cancel, #handle_configuration_done, #handle_continue, #handle_data_breakpoint_info, #handle_disconnect, #handle_evaluate, #handle_initialize, #handle_launch, #handle_loaded_sources, #handle_next, #handle_pause, #handle_restart, #handle_scopes, #handle_set_breakpoints, #handle_set_exception_breakpoints, #handle_set_expression, #handle_set_function_breakpoints, #handle_set_variable, #handle_source, #handle_stack_trace, #handle_step_in, #handle_step_out, #handle_terminate, #handle_threads, #handle_variables

Constructor Details

#initialize(protocol: Protocol.new, session: Session.new, backend_factory: nil, preferred_backend_kind: "process", adapter_command: nil) ⇒ Server

Returns a new instance of Server.



37
38
39
40
41
42
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
72
73
74
# File 'lib/milk_tea/dap/server.rb', line 37

def initialize(protocol: Protocol.new, session: Session.new, backend_factory: nil, preferred_backend_kind: "process", adapter_command: nil)
  @protocol = protocol
  @session = session
  @backend_factory = backend_factory
  @preferred_backend_kind = preferred_backend_kind.to_s.empty? ? "process" : preferred_backend_kind.to_s
  @default_adapter_command = adapter_command&.dup
  @handlers = {}
  @write_mutex = Mutex.new
  @client_request_mutex = Mutex.new
  @pending_client_responses = {}
  @incoming_messages = Queue.new
  @reader_thread = nil
  @background_threads = []
  @background_threads_mutex = Mutex.new
  @runtime_mutex = Mutex.new
  @runtime_pid = nil
  @runtime_paused = false
  @tmp_dirs = []
  @lldb_backend = nil
  @backend_initialized = false
  @backend_capabilities = {}
  @breakpoints_synced_to_backend = false
  @function_breakpoints_synced_to_backend = false
  @exception_breakpoints_synced_to_backend = false
  @backend_start_thread = nil
  @backend_auto_continue_after_configuration = false
  @backend_stopped_thread_id = nil
  @backend_pause_requested = false
  @last_forwarded_continued_signature = nil
  @backend_configuration_mutex = Mutex.new
  @backend_configuration_condition = ConditionVariable.new
  @backend_configuration_ready = false
  @debug_map = nil
  @frame_debug_functions = {}
  @variables_reference_debug_functions = {}
  @reverse_request_timeout = Float(ENV.fetch("MILK_TEA_DAP_REVERSE_REQUEST_TIMEOUT", "15"))
  register_handlers
end

Instance Method Details

#runObject



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/milk_tea/dap/server.rb', line 76

def run
  start_client_reader

  loop do
    message = @incoming_messages.pop
    break if message.nil?
    next if message.equal?(Protocol::INVALID_MESSAGE)

    process_message(message)
    break if @session.should_exit?
  end
ensure
  @backend_start_thread&.join(0.2)
  join_background_threads
  @reader_thread&.join(0.2)
end

#start_client_readerObject



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/milk_tea/dap/server.rb', line 93

def start_client_reader
  return if @reader_thread&.alive?

  @reader_thread = Thread.new do
    loop do
      message = @protocol.read_message
      break if message.nil?
      next if message.equal?(Protocol::INVALID_MESSAGE)

      if message["type"] == "response"
        queue = @client_request_mutex.synchronize do
          @pending_client_responses[message["request_seq"]]
        end
        if queue
          queue.push(message)
          next
        end
      end

      @incoming_messages.push(message)
    end
  ensure
    @incoming_messages.push(nil)
  end
end