Skip to content

Commit 47de54e

Browse files
authored
[lldb-dap] Fix TestDap_attach.py flakiness (#137278)
# Summary This patch makes the `request_attach` wait for events `process` and `initialized` just like `request_launch`. This ensure the DAP session can move forward somewhat correctly. Recently `TestDap_attach.test_terminate_commands` became flaky. It's hitting: ``` lldbsuite/test/tools/lldb-dap/dap_server.py", line 350, in send_recv raise ValueError(desc) ValueError: no response for "disconnect" ``` I took a look at the DAP msg from that test case and noticed: - It's not using the regular attaching, instead it's using the `attachCommands` to launch debug the binary and it will stop at entry. - The `initialized` event returned after the `disconnect` request. Which means lldb-dap didn't really get ready yet. ### NOTE The `dap_server.py` is doing things to mimic the VSCode (or other dap clients) but it had some assumptions. For example, it's still missing the `configurationDone` request and response because it relies on a continue action to trigger the `configurationDone` request. # Test Plan ``` ./bin/llvm-lit -va /Users/wanyi/llvm-upstream/llvm-project/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py ./bin/llvm-lit -va /Users/wanyi/llvm-upstream/llvm-project/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py ``` To test the `wait_for_events` timeout case ``` events = self.wait_for_events(["process", "initialized", "fake", "event"], 1) if events: raise ValueError(f'no events {",".join(events)} found for within timeout 1') ``` Observed <img width="696" alt="image" src="https://github.com/user-attachments/assets/bc97c0ef-d91f-4561-8272-4d36f5f5d4e6" /> ### Also Looks like some test cases should be re-enabled in 0b8dfb5 But only comments was removed. The skip statements survived the change.
1 parent afdc4b1 commit 47de54e

File tree

2 files changed

+17
-7
lines changed

2 files changed

+17
-7
lines changed

lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,17 @@ def wait_for_event(self, filter=None, timeout=None):
380380
)
381381
return None
382382

383+
def wait_for_events(self, events, timeout=None):
384+
"""Wait for a list of events in `events` in any order.
385+
Return the events not hit before the timeout expired"""
386+
events = events[:] # Make a copy to avoid modifying the input
387+
while events:
388+
event_dict = self.wait_for_event(filter=events, timeout=timeout)
389+
if event_dict is None:
390+
break
391+
events.remove(event_dict["event"])
392+
return events
393+
383394
def wait_for_stopped(self, timeout=None):
384395
stopped_events = []
385396
stopped_event = self.wait_for_event(
@@ -618,7 +629,11 @@ def request_attach(
618629
if gdbRemoteHostname is not None:
619630
args_dict["gdb-remote-hostname"] = gdbRemoteHostname
620631
command_dict = {"command": "attach", "type": "request", "arguments": args_dict}
621-
return self.send_recv(command_dict)
632+
response = self.send_recv(command_dict)
633+
634+
if response["success"]:
635+
self.wait_for_events(["process", "initialized"])
636+
return response
622637

623638
def request_breakpointLocations(
624639
self, file_path, line, end_line=None, column=None, end_column=None
@@ -872,9 +887,7 @@ def request_launch(
872887
response = self.send_recv(command_dict)
873888

874889
if response["success"]:
875-
# Wait for a 'process' and 'initialized' event in any order
876-
self.wait_for_event(filter=["process", "initialized"])
877-
self.wait_for_event(filter=["process", "initialized"])
890+
self.wait_for_events(["process", "initialized"])
878891
return response
879892

880893
def request_next(self, threadId, granularity="statement"):

lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ def cleanup():
9393
self.set_and_hit_breakpoint(continueToExit=True)
9494

9595
@skipUnlessDarwin
96-
@skipIfDarwin
9796
@skipIfNetBSD # Hangs on NetBSD as well
9897
def test_by_name_waitFor(self):
9998
"""
@@ -114,7 +113,6 @@ def test_by_name_waitFor(self):
114113
self.attach(program=program, waitFor=True)
115114
self.set_and_hit_breakpoint(continueToExit=True)
116115

117-
@skipIfDarwin
118116
@skipIfNetBSD # Hangs on NetBSD as well
119117
def test_commands(self):
120118
"""
@@ -201,7 +199,6 @@ def test_commands(self):
201199
self.verify_commands("exitCommands", output, exitCommands)
202200
self.verify_commands("terminateCommands", output, terminateCommands)
203201

204-
@skipIfDarwin
205202
@skipIfNetBSD # Hangs on NetBSD as well
206203
@skipIf(
207204
archs=["arm", "aarch64"]

0 commit comments

Comments
 (0)