https://github.com/JDevlieghere updated 
https://github.com/llvm/llvm-project/pull/138219

>From b7391070942219a691a691822477e2a7616be1ab Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jo...@devlieghere.com>
Date: Fri, 2 May 2025 09:59:01 -0700
Subject: [PATCH] [lldb-dap] Change the launch sequence

This PR changes how we treat the launch sequence in lldb-dap.

 - Send the initialized event after we finish handling the initialize
   request, rather than after we finish attaching or launching.
 - Delay handling the launch and attach request until we have handled
   the configurationDone request. The latter is now largely a NO-OP and
   only exists to signal lldb-dap that it can handle the launch and
   attach requests.
 - Delay handling the initial threads requests until we have handled
   the launch or attach request.
 - Make all attaching and launching asynchronous, including when we have
   attach or launch commands. That removes the need to synchronize
   between the request and event thread.

Background: https://discourse.llvm.org/t/reliability-of-the-lldb-dap-tests/86125
---
 .../test/tools/lldb-dap/dap_server.py         |  65 +++++-----
 .../test/tools/lldb-dap/lldbdap_testcase.py   |   7 ++
 .../tools/lldb-dap/attach/TestDAP_attach.py   |   3 +-
 .../attach/TestDAP_attachByPortNum.py         |   8 +-
 .../TestDAP_breakpointEvents.py               |  60 +++------
 .../breakpoint/TestDAP_breakpointLocations.py |   3 +-
 .../breakpoint/TestDAP_setBreakpoints.py      |   3 +-
 .../lldb-dap/commands/TestDAP_commands.py     |   2 -
 .../completions/TestDAP_completions.py        |   6 +-
 .../tools/lldb-dap/console/TestDAP_console.py |   2 +-
 .../disassemble/TestDAP_disassemble.py        |   3 +-
 .../lldb-dap/disconnect/TestDAP_disconnect.py |   6 +-
 .../lldb-dap/evaluate/TestDAP_evaluate.py     |   3 +-
 .../tools/lldb-dap/launch/TestDAP_launch.py   |   4 +-
 .../tools/lldb-dap/memory/TestDAP_memory.py   |   3 +-
 .../lldb-dap/progress/TestDAP_Progress.py     |   2 +-
 .../repl-mode/TestDAP_repl_mode_detection.py  |   2 +-
 .../tools/lldb-dap/restart/TestDAP_restart.py |   1 -
 .../restart/TestDAP_restart_runInTerminal.py  |   1 -
 .../lldb-dap/stop-hooks/TestDAP_stop_hooks.py |   2 +-
 .../lldb-dap/variables/TestDAP_variables.py   |   3 +-
 lldb/tools/lldb-dap/DAP.cpp                   |  39 ++++--
 lldb/tools/lldb-dap/DAP.h                     |   8 +-
 lldb/tools/lldb-dap/EventHelper.cpp           |   2 +-
 .../lldb-dap/Handler/AttachRequestHandler.cpp | 115 ++++++++++--------
 .../ConfigurationDoneRequestHandler.cpp       |  14 +--
 .../Handler/InitializeRequestHandler.cpp      |  44 +++----
 .../lldb-dap/Handler/LaunchRequestHandler.cpp |   7 +-
 .../tools/lldb-dap/Handler/RequestHandler.cpp |  67 ++++++----
 lldb/tools/lldb-dap/Handler/RequestHandler.h  |   1 +
 30 files changed, 252 insertions(+), 234 deletions(-)

diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py 
b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
index 6d9ab770684f1..e10342b72f4f0 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
@@ -132,7 +132,6 @@ def __init__(self, recv, send, init_commands, 
log_file=None):
         self.exit_status = None
         self.initialize_body = None
         self.thread_stop_reasons = {}
-        self.breakpoint_events = []
         self.progress_events = []
         self.reverse_requests = []
         self.module_events = []
@@ -244,13 +243,6 @@ def handle_recv_packet(self, packet):
                 self._process_stopped()
                 tid = body["threadId"]
                 self.thread_stop_reasons[tid] = body
-            elif event == "breakpoint":
-                # Breakpoint events come in when a breakpoint has locations
-                # added or removed. Keep track of them so we can look for them
-                # in tests.
-                self.breakpoint_events.append(packet)
-                # no need to add 'breakpoint' event packets to our packets list
-                return keepGoing
             elif event.startswith("progress"):
                 # Progress events come in as 'progressStart', 'progressUpdate',
                 # and 'progressEnd' events. Keep these around in case test
@@ -412,6 +404,15 @@ def wait_for_stopped(self, timeout=None):
             self.threads = []
         return stopped_events
 
+    def wait_for_breakpoint_events(self, timeout=None):
+        breakpoint_events = []
+        while True:
+            event = self.wait_for_event("breakpoint", timeout=timeout)
+            if not event:
+                break
+            breakpoint_events.append(event)
+        return breakpoint_events
+
     def wait_for_exited(self):
         event_dict = self.wait_for_event("exited")
         if event_dict is None:
@@ -591,6 +592,7 @@ def request_attach(
         attachCommands=None,
         terminateCommands=None,
         coreFile=None,
+        stopOnAttach=True,
         postRunCommands=None,
         sourceMap=None,
         gdbRemotePort=None,
@@ -620,6 +622,8 @@ def request_attach(
             args_dict["attachCommands"] = attachCommands
         if coreFile:
             args_dict["coreFile"] = coreFile
+        if stopOnAttach:
+            args_dict["stopOnEntry"] = stopOnAttach
         if postRunCommands:
             args_dict["postRunCommands"] = postRunCommands
         if sourceMap:
@@ -632,7 +636,7 @@ def request_attach(
         response = self.send_recv(command_dict)
 
         if response["success"]:
-            self.wait_for_events(["process", "initialized"])
+            self.wait_for_event("process")
         return response
 
     def request_breakpointLocations(
@@ -666,10 +670,6 @@ def request_configurationDone(self):
         response = self.send_recv(command_dict)
         if response:
             self.configuration_done_sent = True
-            # Client requests the baseline of currently existing threads after
-            # a successful launch or attach.
-            # Kick off the threads request that follows
-            self.request_threads()
         return response
 
     def _process_stopped(self):
@@ -887,7 +887,7 @@ def request_launch(
         response = self.send_recv(command_dict)
 
         if response["success"]:
-            self.wait_for_events(["process", "initialized"])
+            self.wait_for_event("process")
         return response
 
     def request_next(self, threadId, granularity="statement"):
@@ -1325,6 +1325,26 @@ def attach_options_specified(options):
 
 def run_vscode(dbg, args, options):
     dbg.request_initialize(options.sourceInitFile)
+
+    if options.sourceBreakpoints:
+        source_to_lines = {}
+        for file_line in options.sourceBreakpoints:
+            (path, line) = file_line.split(":")
+            if len(path) == 0 or len(line) == 0:
+                print('error: invalid source with line "%s"' % (file_line))
+
+            else:
+                if path in source_to_lines:
+                    source_to_lines[path].append(int(line))
+                else:
+                    source_to_lines[path] = [int(line)]
+        for source in source_to_lines:
+            dbg.request_setBreakpoints(source, source_to_lines[source])
+    if options.funcBreakpoints:
+        dbg.request_setFunctionBreakpoints(options.funcBreakpoints)
+
+    dbg.request_configurationDone()
+
     if attach_options_specified(options):
         response = dbg.request_attach(
             program=options.program,
@@ -1353,23 +1373,6 @@ def run_vscode(dbg, args, options):
         )
 
     if response["success"]:
-        if options.sourceBreakpoints:
-            source_to_lines = {}
-            for file_line in options.sourceBreakpoints:
-                (path, line) = file_line.split(":")
-                if len(path) == 0 or len(line) == 0:
-                    print('error: invalid source with line "%s"' % (file_line))
-
-                else:
-                    if path in source_to_lines:
-                        source_to_lines[path].append(int(line))
-                    else:
-                        source_to_lines[path] = [int(line)]
-            for source in source_to_lines:
-                dbg.request_setBreakpoints(source, source_to_lines[source])
-        if options.funcBreakpoints:
-            dbg.request_setFunctionBreakpoints(options.funcBreakpoints)
-        dbg.request_configurationDone()
         dbg.wait_for_stopped()
     else:
         if "message" in response:
diff --git 
a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py 
b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
index 2c14bb35162b5..958c7268c0c72 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
@@ -340,6 +340,7 @@ def attach(
         exitCommands=None,
         attachCommands=None,
         coreFile=None,
+        stopOnAttach=True,
         disconnectAutomatically=True,
         terminateCommands=None,
         postRunCommands=None,
@@ -364,6 +365,8 @@ def cleanup():
         self.addTearDownHook(cleanup)
         # Initialize and launch the program
         self.dap_server.request_initialize(sourceInitFile)
+        self.dap_server.wait_for_event("initialized")
+        self.dap_server.request_configurationDone()
         response = self.dap_server.request_attach(
             program=program,
             pid=pid,
@@ -376,6 +379,7 @@ def cleanup():
             attachCommands=attachCommands,
             terminateCommands=terminateCommands,
             coreFile=coreFile,
+            stopOnAttach=stopOnAttach,
             postRunCommands=postRunCommands,
             sourceMap=sourceMap,
             gdbRemotePort=gdbRemotePort,
@@ -434,6 +438,9 @@ def cleanup():
 
         # Initialize and launch the program
         self.dap_server.request_initialize(sourceInitFile)
+        self.dap_server.wait_for_event("initialized")
+        self.dap_server.request_configurationDone()
+
         response = self.dap_server.request_launch(
             program,
             args=args,
diff --git a/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py 
b/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py
index f48d5a7db3c50..b5569642f9d34 100644
--- a/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py
+++ b/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py
@@ -24,9 +24,10 @@ def spawn_and_wait(program, delay):
     process.wait()
 
 
-@skip
 class TestDAP_attach(lldbdap_testcase.DAPTestCaseBase):
     def set_and_hit_breakpoint(self, continueToExit=True):
+        self.dap_server.wait_for_stopped()
+
         source = "main.c"
         breakpoint1_line = line_number(source, "// breakpoint 1")
         lines = [breakpoint1_line]
diff --git a/lldb/test/API/tools/lldb-dap/attach/TestDAP_attachByPortNum.py 
b/lldb/test/API/tools/lldb-dap/attach/TestDAP_attachByPortNum.py
index 7f93b9f2a3a22..7250e67ebcd8c 100644
--- a/lldb/test/API/tools/lldb-dap/attach/TestDAP_attachByPortNum.py
+++ b/lldb/test/API/tools/lldb-dap/attach/TestDAP_attachByPortNum.py
@@ -18,17 +18,17 @@
 import socket
 
 
-@skip
 class TestDAP_attachByPortNum(lldbdap_testcase.DAPTestCaseBase):
     default_timeout = 20
 
     def set_and_hit_breakpoint(self, continueToExit=True):
+        self.dap_server.wait_for_stopped()
+
         source = "main.c"
-        main_source_path = os.path.join(os.getcwd(), source)
-        breakpoint1_line = line_number(main_source_path, "// breakpoint 1")
+        breakpoint1_line = line_number(source, "// breakpoint 1")
         lines = [breakpoint1_line]
         # Set breakpoint in the thread function so we can step the threads
-        breakpoint_ids = self.set_source_breakpoints(main_source_path, lines)
+        breakpoint_ids = self.set_source_breakpoints(source, lines)
         self.assertEqual(
             len(breakpoint_ids), len(lines), "expect correct number of 
breakpoints"
         )
diff --git 
a/lldb/test/API/tools/lldb-dap/breakpoint-events/TestDAP_breakpointEvents.py 
b/lldb/test/API/tools/lldb-dap/breakpoint-events/TestDAP_breakpointEvents.py
index e5590e1b332a0..cdfd3317303e9 100644
--- a/lldb/test/API/tools/lldb-dap/breakpoint-events/TestDAP_breakpointEvents.py
+++ b/lldb/test/API/tools/lldb-dap/breakpoint-events/TestDAP_breakpointEvents.py
@@ -81,52 +81,24 @@ def test_breakpoint_events(self):
                 breakpoint["verified"], "expect foo breakpoint to not be 
verified"
             )
 
-        # Get the stop at the entry point
-        self.continue_to_next_stop()
-
-        # We are now stopped at the entry point to the program. Shared
-        # libraries are not loaded yet (at least on macOS they aren't) and only
-        # the breakpoint in the main executable should be resolved.
-        self.assertEqual(len(self.dap_server.breakpoint_events), 1)
-        event = self.dap_server.breakpoint_events[0]
-        body = event["body"]
-        self.assertEqual(
-            body["reason"], "changed", "breakpoint event should say changed"
-        )
-        breakpoint = body["breakpoint"]
-        self.assertEqual(breakpoint["id"], main_bp_id)
-        self.assertTrue(breakpoint["verified"], "main breakpoint should be 
resolved")
-
-        # Clear the list of breakpoint events so we don't see this one again.
-        self.dap_server.breakpoint_events.clear()
+        # Flush the breakpoint events.
+        self.dap_server.wait_for_breakpoint_events(timeout=5)
 
         # Continue to the breakpoint
         self.continue_to_breakpoints(dap_breakpoint_ids)
 
-        # When the process launches, we first expect to see both the main and
-        # foo breakpoint as unresolved.
-        for event in self.dap_server.breakpoint_events[:2]:
-            body = event["body"]
-            self.assertEqual(
-                body["reason"], "changed", "breakpoint event should say 
changed"
-            )
-            breakpoint = body["breakpoint"]
-            self.assertIn(str(breakpoint["id"]), dap_breakpoint_ids)
-            self.assertFalse(breakpoint["verified"], "breakpoint should be 
unresolved")
+        verified_breakpoint_ids = []
+        unverified_breakpoint_ids = []
+        for breakpoint_event in 
self.dap_server.wait_for_breakpoint_events(timeout=5):
+            breakpoint = breakpoint_event["body"]["breakpoint"]
+            id = breakpoint["id"]
+            if breakpoint["verified"]:
+                verified_breakpoint_ids.append(id)
+            else:
+                unverified_breakpoint_ids.append(id)
 
-        # Then, once the dynamic loader has given us a load address, they
-        # should show up as resolved again.
-        for event in self.dap_server.breakpoint_events[3:]:
-            body = event["body"]
-            self.assertEqual(
-                body["reason"], "changed", "breakpoint event should say 
changed"
-            )
-            breakpoint = body["breakpoint"]
-            self.assertIn(str(breakpoint["id"]), dap_breakpoint_ids)
-            self.assertTrue(breakpoint["verified"], "breakpoint should be 
resolved")
-            self.assertNotIn(
-                "source",
-                breakpoint,
-                "breakpoint event should not return a source object",
-            )
-            self.assertIn("line", breakpoint, "breakpoint event should have 
line")
+        self.assertIn(main_bp_id, unverified_breakpoint_ids)
+        self.assertIn(foo_bp_id, unverified_breakpoint_ids)
+
+        self.assertIn(main_bp_id, verified_breakpoint_ids)
+        self.assertIn(foo_bp_id, verified_breakpoint_ids)
diff --git 
a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_breakpointLocations.py 
b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_breakpointLocations.py
index 4a99cacc761a3..1058157e2c668 100644
--- a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_breakpointLocations.py
+++ b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_breakpointLocations.py
@@ -11,8 +11,7 @@
 import lldbdap_testcase
 import os
 
-# DAP tests are flakey, see https://github.com/llvm/llvm-project/issues/137660.
-@skip
+
 class TestDAP_breakpointLocations(lldbdap_testcase.DAPTestCaseBase):
     def setUp(self):
         lldbdap_testcase.DAPTestCaseBase.setUp(self)
diff --git a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setBreakpoints.py 
b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setBreakpoints.py
index 6c6681804f250..26df2573555df 100644
--- a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setBreakpoints.py
+++ b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setBreakpoints.py
@@ -11,8 +11,7 @@
 import lldbdap_testcase
 import os
 
-# DAP tests are flakey, see https://github.com/llvm/llvm-project/issues/137660.
-@skip
+
 class TestDAP_setBreakpoints(lldbdap_testcase.DAPTestCaseBase):
     def setUp(self):
         lldbdap_testcase.DAPTestCaseBase.setUp(self)
diff --git a/lldb/test/API/tools/lldb-dap/commands/TestDAP_commands.py 
b/lldb/test/API/tools/lldb-dap/commands/TestDAP_commands.py
index 4aecf9a665c06..223258fbdd3dc 100644
--- a/lldb/test/API/tools/lldb-dap/commands/TestDAP_commands.py
+++ b/lldb/test/API/tools/lldb-dap/commands/TestDAP_commands.py
@@ -6,8 +6,6 @@
 from lldbsuite.test.decorators import *
 
 
-# DAP tests are flakey, see https://github.com/llvm/llvm-project/issues/137660.
-@skip
 class TestDAP_commands(lldbdap_testcase.DAPTestCaseBase):
     def test_command_directive_quiet_on_success(self):
         program = self.getBuildArtifact("a.out")
diff --git a/lldb/test/API/tools/lldb-dap/completions/TestDAP_completions.py 
b/lldb/test/API/tools/lldb-dap/completions/TestDAP_completions.py
index 210e591bff426..455ac84168baf 100644
--- a/lldb/test/API/tools/lldb-dap/completions/TestDAP_completions.py
+++ b/lldb/test/API/tools/lldb-dap/completions/TestDAP_completions.py
@@ -44,9 +44,9 @@ def verify_completions(self, actual_list, expected_list, 
not_expected_list=[]):
             self.assertNotIn(not_expected_item, actual_list)
 
 
-    def setup_debugee(self):
+    def setup_debugee(self, stopOnEntry=False):
         program = self.getBuildArtifact("a.out")
-        self.build_and_launch(program)
+        self.build_and_launch(program, stopOnEntry=stopOnEntry)
 
         source = "main.cpp"
         breakpoint1_line = line_number(source, "// breakpoint 1")
@@ -235,7 +235,7 @@ def test_auto_completions(self):
         """
         Tests completion requests in "repl-mode=auto"
         """
-        self.setup_debugee()
+        self.setup_debugee(stopOnEntry=True)
 
         res = self.dap_server.request_evaluate(
             "`lldb-dap repl-mode auto", context="repl"
diff --git a/lldb/test/API/tools/lldb-dap/console/TestDAP_console.py 
b/lldb/test/API/tools/lldb-dap/console/TestDAP_console.py
index b07c4f871d73b..65a1bc04c7cd7 100644
--- a/lldb/test/API/tools/lldb-dap/console/TestDAP_console.py
+++ b/lldb/test/API/tools/lldb-dap/console/TestDAP_console.py
@@ -167,7 +167,7 @@ def test_exit_status_message_ok(self):
 
     def test_diagnositcs(self):
         program = self.getBuildArtifact("a.out")
-        self.build_and_launch(program)
+        self.build_and_launch(program, stopOnEntry=True)
 
         core = self.getBuildArtifact("minidump.core")
         self.yaml2obj("minidump.yaml", core)
diff --git a/lldb/test/API/tools/lldb-dap/disassemble/TestDAP_disassemble.py 
b/lldb/test/API/tools/lldb-dap/disassemble/TestDAP_disassemble.py
index ebecb349ac177..9e8ef5b289f2e 100644
--- a/lldb/test/API/tools/lldb-dap/disassemble/TestDAP_disassemble.py
+++ b/lldb/test/API/tools/lldb-dap/disassemble/TestDAP_disassemble.py
@@ -10,8 +10,7 @@
 import lldbdap_testcase
 import os
 
-# DAP tests are flakey, see https://github.com/llvm/llvm-project/issues/137660.
-@skip
+
 class TestDAP_disassemble(lldbdap_testcase.DAPTestCaseBase):
     @skipIfWindows
     def test_disassemble(self):
diff --git a/lldb/test/API/tools/lldb-dap/disconnect/TestDAP_disconnect.py 
b/lldb/test/API/tools/lldb-dap/disconnect/TestDAP_disconnect.py
index 0cb792d662a80..09e3f62f0eead 100644
--- a/lldb/test/API/tools/lldb-dap/disconnect/TestDAP_disconnect.py
+++ b/lldb/test/API/tools/lldb-dap/disconnect/TestDAP_disconnect.py
@@ -31,7 +31,7 @@ def test_launch(self):
         created.
         """
         program = self.getBuildArtifact("a.out")
-        self.build_and_launch(program, disconnectAutomatically=False)
+        self.build_and_launch(program, stopOnEntry=True, 
disconnectAutomatically=False)
 
         # We set a breakpoint right before the side effect file is created
         self.set_source_breakpoints(
@@ -39,7 +39,11 @@ def test_launch(self):
         )
         self.continue_to_next_stop()
 
+        # verify we haven't produced the side effect file yet
+        self.assertFalse(os.path.exists(program + ".side_effect"))
+
         self.dap_server.request_disconnect()
+
         # verify we didn't produce the side effect file
         time.sleep(1)
         self.assertFalse(os.path.exists(program + ".side_effect"))
diff --git a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py 
b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py
index d97fda730c46a..e2f843bd337a6 100644
--- a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py
+++ b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py
@@ -10,8 +10,7 @@
 from lldbsuite.test.decorators import *
 from lldbsuite.test.lldbtest import *
 
-# DAP tests are flakey, see https://github.com/llvm/llvm-project/issues/137660.
-@skip
+
 class TestDAP_evaluate(lldbdap_testcase.DAPTestCaseBase):
     def assertEvaluate(self, expression, regex):
         self.assertRegex(
diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py 
b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
index 931456299e03e..604a41678500c 100644
--- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
+++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
@@ -88,8 +88,8 @@ def test_stopOnEntry(self):
         """
         program = self.getBuildArtifact("a.out")
         self.build_and_launch(program, stopOnEntry=True)
-        self.set_function_breakpoints(["main"])
-        stopped_events = self.continue_to_next_stop()
+
+        stopped_events = self.dap_server.wait_for_stopped()
         for stopped_event in stopped_events:
             if "body" in stopped_event:
                 body = stopped_event["body"]
diff --git a/lldb/test/API/tools/lldb-dap/memory/TestDAP_memory.py 
b/lldb/test/API/tools/lldb-dap/memory/TestDAP_memory.py
index c71ba871b8a22..ea43fccf016a7 100644
--- a/lldb/test/API/tools/lldb-dap/memory/TestDAP_memory.py
+++ b/lldb/test/API/tools/lldb-dap/memory/TestDAP_memory.py
@@ -10,8 +10,7 @@
 import lldbdap_testcase
 import os
 
-# DAP tests are flakey, see https://github.com/llvm/llvm-project/issues/137660.
-@skip
+
 class TestDAP_memory(lldbdap_testcase.DAPTestCaseBase):
     def test_memory_refs_variables(self):
         """
diff --git a/lldb/test/API/tools/lldb-dap/progress/TestDAP_Progress.py 
b/lldb/test/API/tools/lldb-dap/progress/TestDAP_Progress.py
index fee63655de0da..0f94b50c31fba 100755
--- a/lldb/test/API/tools/lldb-dap/progress/TestDAP_Progress.py
+++ b/lldb/test/API/tools/lldb-dap/progress/TestDAP_Progress.py
@@ -50,7 +50,7 @@ def verify_progress_events(
     @skipIfWindows
     def test(self):
         program = self.getBuildArtifact("a.out")
-        self.build_and_launch(program)
+        self.build_and_launch(program, stopOnEntry=True)
         progress_emitter = os.path.join(os.getcwd(), "Progress_emitter.py")
         self.dap_server.request_evaluate(
             f"`command script import {progress_emitter}", context="repl"
diff --git 
a/lldb/test/API/tools/lldb-dap/repl-mode/TestDAP_repl_mode_detection.py 
b/lldb/test/API/tools/lldb-dap/repl-mode/TestDAP_repl_mode_detection.py
index c6f59949d668e..81edcdf4bd0f9 100644
--- a/lldb/test/API/tools/lldb-dap/repl-mode/TestDAP_repl_mode_detection.py
+++ b/lldb/test/API/tools/lldb-dap/repl-mode/TestDAP_repl_mode_detection.py
@@ -20,7 +20,7 @@ def assertEvaluate(self, expression, regex):
 
     def test_completions(self):
         program = self.getBuildArtifact("a.out")
-        self.build_and_launch(program)
+        self.build_and_launch(program, stopOnEntry=True)
 
         source = "main.cpp"
         breakpoint1_line = line_number(source, "// breakpoint 1")
diff --git a/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart.py 
b/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart.py
index 36fa0bd40183f..5f95c7bfb1556 100644
--- a/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart.py
+++ b/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart.py
@@ -22,7 +22,6 @@ def test_basic_functionality(self):
         [bp_A, bp_B] = self.set_source_breakpoints("main.c", [line_A, line_B])
 
         # Verify we hit A, then B.
-        self.dap_server.request_configurationDone()
         self.verify_breakpoint_hit([bp_A])
         self.dap_server.request_continue()
         self.verify_breakpoint_hit([bp_B])
diff --git 
a/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart_runInTerminal.py 
b/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart_runInTerminal.py
index a94c9860c1508..eed769a5a0cc6 100644
--- a/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart_runInTerminal.py
+++ b/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart_runInTerminal.py
@@ -74,7 +74,6 @@ def test_stopOnEntry(self):
         program = self.getBuildArtifact("a.out")
         self.build_and_launch(program, runInTerminal=True, stopOnEntry=True)
         [bp_main] = self.set_function_breakpoints(["main"])
-        self.dap_server.request_configurationDone()
 
         # When using stopOnEntry, configurationDone doesn't result in a running
         # process, we should immediately get a stopped event instead.
diff --git a/lldb/test/API/tools/lldb-dap/stop-hooks/TestDAP_stop_hooks.py 
b/lldb/test/API/tools/lldb-dap/stop-hooks/TestDAP_stop_hooks.py
index 70c11a63a79f7..7e28a5af4331c 100644
--- a/lldb/test/API/tools/lldb-dap/stop-hooks/TestDAP_stop_hooks.py
+++ b/lldb/test/API/tools/lldb-dap/stop-hooks/TestDAP_stop_hooks.py
@@ -19,7 +19,7 @@ def test_stop_hooks_before_run(self):
         self.build_and_launch(program, stopOnEntry=True, 
preRunCommands=preRunCommands)
 
         # The first stop is on entry.
-        self.continue_to_next_stop()
+        self.dap_server.wait_for_stopped()
 
         breakpoint_ids = self.set_function_breakpoints(["main"])
         # This request hangs if the race happens, because, in that case, the
diff --git a/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py 
b/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py
index 901c260d7d413..286bf3390a440 100644
--- a/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py
+++ b/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py
@@ -17,8 +17,7 @@ def make_buffer_verify_dict(start_idx, count, offset=0):
         verify_dict["[%i]" % (i)] = {"type": "int", "value": str(i + offset)}
     return verify_dict
 
-# DAP tests are flakey, see https://github.com/llvm/llvm-project/issues/137660.
-@skip
+
 class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase):
     def verify_values(self, verify_dict, actual, varref_dict=None, 
expression=None):
         if "equals" in verify_dict:
diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp
index 4b631484c9fab..62c60cc3a9b3b 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -84,8 +84,8 @@ DAP::DAP(Log *log, const ReplMode default_repl_mode,
     : log(log), transport(transport), broadcaster("lldb-dap"),
       exception_breakpoints(), focus_tid(LLDB_INVALID_THREAD_ID),
       stop_at_entry(false), is_attach(false),
-      restarting_process_id(LLDB_INVALID_PROCESS_ID),
-      configuration_done_sent(false), waiting_for_run_in_terminal(false),
+      restarting_process_id(LLDB_INVALID_PROCESS_ID), 
configuration_done(false),
+      waiting_for_run_in_terminal(false),
       progress_event_reporter(
           [&](const ProgressEvent &event) { SendJSON(event.ToJSON()); }),
       reverse_request_seq(0), repl_mode(default_repl_mode) {
@@ -893,10 +893,19 @@ llvm::Error DAP::Loop() {
             return errWrapper;
           }
 
+          // The launch sequence is special and we need to carefully handle
+          // packets in the right order. Until we've handled configurationDone,
+          bool add_to_pending_queue = false;
+
           if (const protocol::Request *req =
-                  std::get_if<protocol::Request>(&*next);
-              req && req->command == "disconnect") {
-            disconnecting = true;
+                  std::get_if<protocol::Request>(&*next)) {
+            llvm::StringRef command = req->command;
+            if (command == "disconnect")
+              disconnecting = true;
+            if (!configuration_done)
+              add_to_pending_queue =
+                  command != "initialize" && command != "configurationDone" &&
+                  command != "disconnect" && !command.ends_with("Breakpoints");
           }
 
           const std::optional<CancelArguments> cancel_args =
@@ -924,7 +933,8 @@ llvm::Error DAP::Loop() {
 
           {
             std::lock_guard<std::mutex> guard(m_queue_mutex);
-            m_queue.push_back(std::move(*next));
+            auto &queue = add_to_pending_queue ? m_pending_queue : m_queue;
+            queue.push_back(std::move(*next));
           }
           m_queue_cv.notify_one();
         }
@@ -938,16 +948,19 @@ llvm::Error DAP::Loop() {
     StopEventHandlers();
   });
 
-  while (!disconnecting || !m_queue.empty()) {
+  while (true) {
     std::unique_lock<std::mutex> lock(m_queue_mutex);
     m_queue_cv.wait(lock, [&] { return disconnecting || !m_queue.empty(); });
 
-    if (m_queue.empty())
+    if (disconnecting && m_queue.empty())
       break;
 
     Message next = m_queue.front();
     m_queue.pop_front();
 
+    // Unlock while we're processing the event.
+    lock.unlock();
+
     if (!HandleObject(next))
       return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                      "unhandled packet");
@@ -1219,6 +1232,16 @@ void DAP::SetConfiguration(const protocol::Configuration 
&config,
     SetThreadFormat(*configuration.customThreadFormat);
 }
 
+void DAP::SetConfigurationDone() {
+  {
+    std::lock_guard<std::mutex> guard(m_queue_mutex);
+    std::copy(m_pending_queue.begin(), m_pending_queue.end(),
+              std::front_inserter(m_queue));
+    configuration_done = true;
+  }
+  m_queue_cv.notify_all();
+}
+
 void DAP::SetFrameFormat(llvm::StringRef format) {
   if (format.empty())
     return;
diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h
index 88eedb0860cf1..b581ae759b1bc 100644
--- a/lldb/tools/lldb-dap/DAP.h
+++ b/lldb/tools/lldb-dap/DAP.h
@@ -188,7 +188,7 @@ struct DAP {
   // shutting down the entire adapter. When we're restarting, we keep the id of
   // the old process here so we can detect this case and keep running.
   lldb::pid_t restarting_process_id;
-  bool configuration_done_sent;
+  bool configuration_done;
   llvm::StringMap<std::unique_ptr<BaseRequestHandler>> request_handlers;
   bool waiting_for_run_in_terminal;
   ProgressEventReporter progress_event_reporter;
@@ -251,6 +251,8 @@ struct DAP {
   /// Configures the debug adapter for launching/attaching.
   void SetConfiguration(const protocol::Configuration &confing, bool 
is_attach);
 
+  void SetConfigurationDone();
+
   /// Configure source maps based on the current `DAPConfiguration`.
   void ConfigureSourceMaps();
 
@@ -417,8 +419,10 @@ struct DAP {
   lldb::SBMutex GetAPIMutex() const { return target.GetAPIMutex(); }
 
 private:
-  std::mutex m_queue_mutex;
+  /// Queue for all incoming messages.
   std::deque<protocol::Message> m_queue;
+  std::deque<protocol::Message> m_pending_queue;
+  std::mutex m_queue_mutex;
   std::condition_variable m_queue_cv;
 
   std::mutex m_cancelled_requests_mutex;
diff --git a/lldb/tools/lldb-dap/EventHelper.cpp 
b/lldb/tools/lldb-dap/EventHelper.cpp
index 2c659f39f4b66..ed2d8700c26b0 100644
--- a/lldb/tools/lldb-dap/EventHelper.cpp
+++ b/lldb/tools/lldb-dap/EventHelper.cpp
@@ -222,7 +222,7 @@ void SendContinuedEvent(DAP &dap) {
 
   // If the focus thread is not set then we haven't reported any thread status
   // to the client, so nothing to report.
-  if (!dap.configuration_done_sent || dap.focus_tid == LLDB_INVALID_THREAD_ID) 
{
+  if (!dap.configuration_done || dap.focus_tid == LLDB_INVALID_THREAD_ID) {
     return;
   }
 
diff --git a/lldb/tools/lldb-dap/Handler/AttachRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/AttachRequestHandler.cpp
index 7a0f091128e4a..5dc9c3f9772e3 100644
--- a/lldb/tools/lldb-dap/Handler/AttachRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/AttachRequestHandler.cpp
@@ -133,61 +133,70 @@ void AttachRequestHandler::operator()(const 
llvm::json::Object &request) const {
     dap.SendOutput(OutputType::Console,
                    llvm::StringRef(attach_msg, attach_msg_len));
   }
-  if (attachCommands.empty()) {
-    // No "attachCommands", just attach normally.
 
-    // Disable async events so the attach will be successful when we return 
from
-    // the launch call and the launch will happen synchronously
+  {
+    // Perform the launch in synchronous mode so that we don't have to worry
+    // about process state changes during the launch.
     ScopeSyncMode scope_sync_mode(dap.debugger);
-
-    if (core_file.empty()) {
-      if ((pid != LLDB_INVALID_PROCESS_ID) &&
-          (gdb_remote_port != invalid_port)) {
-        // If both pid and port numbers are specified.
-        error.SetErrorString("The user can't specify both pid and port");
-      } else if (gdb_remote_port != invalid_port) {
-        // If port is specified and pid is not.
-        lldb::SBListener listener = dap.debugger.GetListener();
-
-        // If the user hasn't provided the hostname property, default localhost
-        // being used.
-        std::string connect_url =
-            llvm::formatv("connect://{0}:", gdb_remote_hostname);
-        connect_url += std::to_string(gdb_remote_port);
-        dap.target.ConnectRemote(listener, connect_url.c_str(), "gdb-remote",
-                                 error);
+    if (attachCommands.empty()) {
+      // No "attachCommands", just attach normally.
+      if (core_file.empty()) {
+        if ((pid != LLDB_INVALID_PROCESS_ID) &&
+            (gdb_remote_port != invalid_port)) {
+          // If both pid and port numbers are specified.
+          error.SetErrorString("The user can't specify both pid and port");
+        } else if (gdb_remote_port != invalid_port) {
+          // If port is specified and pid is not.
+          lldb::SBListener listener = dap.debugger.GetListener();
+
+          // If the user hasn't provided the hostname property, default
+          // localhost being used.
+          std::string connect_url =
+              llvm::formatv("connect://{0}:", gdb_remote_hostname);
+          connect_url += std::to_string(gdb_remote_port);
+          dap.target.ConnectRemote(listener, connect_url.c_str(), "gdb-remote",
+                                   error);
+        } else {
+          // Attach by pid or process name.
+          lldb::SBAttachInfo attach_info;
+          if (pid != LLDB_INVALID_PROCESS_ID)
+            attach_info.SetProcessID(pid);
+          else if (dap.configuration.program.has_value())
+            attach_info.SetExecutable(dap.configuration.program->data());
+          attach_info.SetWaitForLaunch(wait_for, false /*async*/);
+          dap.target.Attach(attach_info, error);
+        }
       } else {
-        // Attach by pid or process name.
-        lldb::SBAttachInfo attach_info;
-        if (pid != LLDB_INVALID_PROCESS_ID)
-          attach_info.SetProcessID(pid);
-        else if (dap.configuration.program.has_value())
-          attach_info.SetExecutable(dap.configuration.program->data());
-        attach_info.SetWaitForLaunch(wait_for, false /*async*/);
-        dap.target.Attach(attach_info, error);
+        dap.target.LoadCore(core_file.data(), error);
       }
     } else {
-      dap.target.LoadCore(core_file.data(), error);
-    }
-  } else {
-    // We have "attachCommands" that are a set of commands that are expected
-    // to execute the commands after which a process should be created. If 
there
-    // is no valid process after running these commands, we have failed.
-    if (llvm::Error err = dap.RunAttachCommands(attachCommands)) {
-      response["success"] = false;
-      EmplaceSafeString(response, "message", llvm::toString(std::move(err)));
-      dap.SendJSON(llvm::json::Value(std::move(response)));
-      return;
+      // We have "attachCommands" that are a set of commands that are expected
+      // to execute the commands after which a process should be created. If
+      // there is no valid process after running these commands, we have 
failed.
+      if (llvm::Error err = dap.RunAttachCommands(attachCommands)) {
+        response["success"] = false;
+        EmplaceSafeString(response, "message", llvm::toString(std::move(err)));
+        dap.SendJSON(llvm::json::Value(std::move(response)));
+        return;
+      }
+      // The custom commands might have created a new target so we should use
+      // the selected target after these commands are run.
+      dap.target = dap.debugger.GetSelectedTarget();
     }
-    // The custom commands might have created a new target so we should use the
-    // selected target after these commands are run.
-    dap.target = dap.debugger.GetSelectedTarget();
-
-    // Make sure the process is attached and stopped before proceeding as the
-    // the launch commands are not run using the synchronous mode.
-    error = dap.WaitForProcessToStop(std::chrono::seconds(timeout_seconds));
   }
 
+  // Make sure the process is attached and stopped.
+  error = dap.WaitForProcessToStop(std::chrono::seconds(timeout_seconds));
+
+  // Clients can request a baseline of currently existing threads after
+  // we acknowledge the configurationDone request.
+  // Client requests the baseline of currently existing threads after
+  // a successful or attach by sending a 'threads' request
+  // right after receiving the configurationDone response.
+  // Obtain the list of threads before we resume the process
+  dap.initial_thread_list =
+      GetThreads(dap.target.GetProcess(), dap.thread_format);
+
   if (error.Success() && core_file.empty()) {
     auto attached_pid = dap.target.GetProcess().GetProcessID();
     if (attached_pid == LLDB_INVALID_PROCESS_ID) {
@@ -206,9 +215,17 @@ void AttachRequestHandler::operator()(const 
llvm::json::Object &request) const {
   }
 
   dap.SendJSON(llvm::json::Value(std::move(response)));
+
+  // FIXME: Move this into PostRun.
   if (error.Success()) {
-    SendProcessEvent(dap, Attach);
-    dap.SendJSON(CreateEventObject("initialized"));
+    if (dap.target.GetProcess().IsValid()) {
+      SendProcessEvent(dap, Attach);
+
+      if (dap.stop_at_entry)
+        SendThreadStoppedEvent(dap);
+      else
+        dap.target.GetProcess().Continue();
+    }
   }
 }
 
diff --git a/lldb/tools/lldb-dap/Handler/ConfigurationDoneRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/ConfigurationDoneRequestHandler.cpp
index f39bbdefdbb95..802c28d7b8904 100644
--- a/lldb/tools/lldb-dap/Handler/ConfigurationDoneRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/ConfigurationDoneRequestHandler.cpp
@@ -47,21 +47,11 @@ namespace lldb_dap {
 
 void ConfigurationDoneRequestHandler::operator()(
     const llvm::json::Object &request) const {
+  dap.SetConfigurationDone();
+
   llvm::json::Object response;
   FillResponse(request, response);
   dap.SendJSON(llvm::json::Value(std::move(response)));
-  dap.configuration_done_sent = true;
-  if (dap.stop_at_entry)
-    SendThreadStoppedEvent(dap);
-  else {
-    // Client requests the baseline of currently existing threads after
-    // a successful launch or attach by sending a 'threads' request
-    // right after receiving the configurationDone response.
-    // Obtain the list of threads before we resume the process
-    dap.initial_thread_list =
-        GetThreads(dap.target.GetProcess(), dap.thread_format);
-    dap.target.GetProcess().Continue();
-  }
 }
 
 } // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
index ce34c52bcc334..aa947d3cb5ab9 100644
--- a/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
@@ -140,43 +140,28 @@ static void EventThreadFunction(DAP &dap) {
         lldb::SBProcess process = lldb::SBProcess::GetProcessFromEvent(event);
         if (event_mask & lldb::SBProcess::eBroadcastBitStateChanged) {
           auto state = lldb::SBProcess::GetStateFromEvent(event);
+
+          DAP_LOG(dap.log, "State = {0}", state);
           switch (state) {
+          case lldb::eStateConnected:
+          case lldb::eStateDetached:
           case lldb::eStateInvalid:
-            // Not a state event
-            break;
           case lldb::eStateUnloaded:
             break;
-          case lldb::eStateConnected:
-            break;
           case lldb::eStateAttaching:
-            break;
-          case lldb::eStateLaunching:
-            break;
-          case lldb::eStateStepping:
-            break;
           case lldb::eStateCrashed:
-            break;
-          case lldb::eStateDetached:
-            break;
-          case lldb::eStateSuspended:
-            break;
+          case lldb::eStateLaunching:
           case lldb::eStateStopped:
-            // We launch and attach in synchronous mode then the first stop
-            // event will not be delivered. If we use "launchCommands" during a
-            // launch or "attachCommands" during an attach we might some 
process
-            // stop events which we do not want to send an event for. We will
-            // manually send a stopped event in request_configurationDone(...)
-            // so don't send any before then.
-            if (dap.configuration_done_sent) {
-              // Only report a stopped event if the process was not
-              // automatically restarted.
-              if (!lldb::SBProcess::GetRestartedFromEvent(event)) {
-                SendStdOutStdErr(dap, process);
-                SendThreadStoppedEvent(dap);
-              }
+          case lldb::eStateSuspended:
+            // Only report a stopped event if the process was not
+            // automatically restarted.
+            if (!lldb::SBProcess::GetRestartedFromEvent(event)) {
+              SendStdOutStdErr(dap, process);
+              SendThreadStoppedEvent(dap);
             }
             break;
           case lldb::eStateRunning:
+          case lldb::eStateStepping:
             dap.WillContinue();
             SendContinuedEvent(dap);
             break;
@@ -284,6 +269,7 @@ llvm::Expected<InitializeResponseBody> 
InitializeRequestHandler::Run(
   // Do not source init files until in/out/err are configured.
   dap.debugger = lldb::SBDebugger::Create(false);
   dap.debugger.SetInputFile(dap.in);
+  dap.target = dap.debugger.GetDummyTarget();
 
   llvm::Expected<int> out_fd = dap.out.GetWriteFileDescriptor();
   if (!out_fd)
@@ -338,4 +324,8 @@ llvm::Expected<InitializeResponseBody> 
InitializeRequestHandler::Run(
   return dap.GetCapabilities();
 }
 
+void InitializeRequestHandler::PostRun() const {
+  dap.SendJSON(CreateEventObject("initialized"));
+}
+
 } // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/Handler/LaunchRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/LaunchRequestHandler.cpp
index 3e4532e754ec6..7e0e76935dd02 100644
--- a/lldb/tools/lldb-dap/Handler/LaunchRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/LaunchRequestHandler.cpp
@@ -71,9 +71,12 @@ void LaunchRequestHandler::PostRun() const {
   if (dap.target.GetProcess().IsValid()) {
     // Attach happens when launching with runInTerminal.
     SendProcessEvent(dap, dap.is_attach ? Attach : Launch);
-  }
 
-  dap.SendJSON(CreateEventObject("initialized"));
+    if (dap.stop_at_entry)
+      SendThreadStoppedEvent(dap);
+    else
+      dap.target.GetProcess().Continue();
+  }
 }
 
 } // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
index 7a75cd93abc19..282c5f4ab15a5 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
@@ -8,6 +8,7 @@
 
 #include "Handler/RequestHandler.h"
 #include "DAP.h"
+#include "EventHelper.h"
 #include "Handler/ResponseHandler.h"
 #include "JSONUtils.h"
 #include "LLDBUtils.h"
@@ -162,7 +163,7 @@ RunInTerminal(DAP &dap, const 
protocol::LaunchRequestArguments &arguments) {
   dap.target.GetProcess().Continue();
 
   // Now that the actual target is just starting (i.e. exec was just invoked),
-  // we return the debugger to its async state.
+  // we return the debugger to its sync state.
   scope_sync_mode.reset();
 
   // If sending the notification failed, the launcher should be dead by now and
@@ -238,35 +239,47 @@ llvm::Error BaseRequestHandler::LaunchProcess(
   launch_info.SetLaunchFlags(flags | lldb::eLaunchFlagDebug |
                              lldb::eLaunchFlagStopAtEntry);
 
-  if (arguments.runInTerminal) {
-    if (llvm::Error err = RunInTerminal(dap, arguments))
-      return err;
-  } else if (launchCommands.empty()) {
-    lldb::SBError error;
-    // Disable async events so the launch will be successful when we return 
from
-    // the launch call and the launch will happen synchronously
+  {
+    // Perform the launch in synchronous mode so that we don't have to worry
+    // about process state changes during the launch.
     ScopeSyncMode scope_sync_mode(dap.debugger);
-    dap.target.Launch(launch_info, error);
-    if (error.Fail())
-      return llvm::make_error<DAPError>(error.GetCString());
-  } else {
-    // Set the launch info so that run commands can access the configured
-    // launch details.
-    dap.target.SetLaunchInfo(launch_info);
-    if (llvm::Error err = dap.RunLaunchCommands(launchCommands))
-      return err;
-
-    // The custom commands might have created a new target so we should use the
-    // selected target after these commands are run.
-    dap.target = dap.debugger.GetSelectedTarget();
-    // Make sure the process is launched and stopped at the entry point before
-    // proceeding as the launch commands are not run using the synchronous
-    // mode.
-    lldb::SBError error = dap.WaitForProcessToStop(arguments.timeout);
-    if (error.Fail())
-      return llvm::make_error<DAPError>(error.GetCString());
+
+    if (arguments.runInTerminal) {
+      if (llvm::Error err = RunInTerminal(dap, arguments))
+        return err;
+    } else if (launchCommands.empty()) {
+      lldb::SBError error;
+      dap.target.Launch(launch_info, error);
+      if (error.Fail())
+        return llvm::make_error<DAPError>(error.GetCString());
+    } else {
+      // Set the launch info so that run commands can access the configured
+      // launch details.
+      dap.target.SetLaunchInfo(launch_info);
+      if (llvm::Error err = dap.RunLaunchCommands(launchCommands))
+        return err;
+
+      // The custom commands might have created a new target so we should use
+      // the selected target after these commands are run.
+      dap.target = dap.debugger.GetSelectedTarget();
+    }
   }
 
+  // Make sure the process is launched and stopped at the entry point before
+  // proceeding.
+  lldb::SBError error = dap.WaitForProcessToStop(arguments.timeout);
+  if (error.Fail())
+    return llvm::make_error<DAPError>(error.GetCString());
+
+  // Clients can request a baseline of currently existing threads after
+  // we acknowledge the configurationDone request.
+  // Client requests the baseline of currently existing threads after
+  // a successful or attach by sending a 'threads' request
+  // right after receiving the configurationDone response.
+  // Obtain the list of threads before we resume the process
+  dap.initial_thread_list =
+      GetThreads(dap.target.GetProcess(), dap.thread_format);
+
   return llvm::Error::success();
 }
 
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h 
b/lldb/tools/lldb-dap/Handler/RequestHandler.h
index fa3d76ed4a125..dec35c5dce1e5 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.h
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h
@@ -282,6 +282,7 @@ class InitializeRequestHandler
   static llvm::StringLiteral GetCommand() { return "initialize"; }
   llvm::Expected<protocol::InitializeResponseBody>
   Run(const protocol::InitializeRequestArguments &args) const override;
+  void PostRun() const override;
 };
 
 class LaunchRequestHandler

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to