Skip to content

Commit 75ae4d8

Browse files
JDevliegherevinay-deshmukh
authored andcommitted
[lldb] Correctly detach (rather than kill) when connecting with gdb-remote (llvm#166869)
We weren't setting `m_should_detach` when going through the `DoConnectRemote` code path. This meant that when you would attaches to a remote process with `gdb-remote <port>` and use Ctrl+D, it would kill the process instead of detach from it. rdar://156111423
1 parent 3c373fa commit 75ae4d8

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

lldb/source/Target/Process.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3256,6 +3256,7 @@ Status Process::ConnectRemote(llvm::StringRef remote_url) {
32563256
if (state == eStateStopped || state == eStateCrashed) {
32573257
// If we attached and actually have a process on the other end, then
32583258
// this ended up being the equivalent of an attach.
3259+
SetShouldDetach(true);
32593260
CompleteAttach();
32603261

32613262
// This delays passing the stopped event to listeners till
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
"""
2+
Test that ConnectRemote sets ShouldDetach flag correctly.
3+
4+
When connecting to a remote process that stops after connection,
5+
the process should be marked for detach (not kill) on destruction.
6+
"""
7+
8+
import lldb
9+
from lldbsuite.test.lldbtest import *
10+
from lldbsuite.test.decorators import *
11+
from lldbsuite.test.gdbclientutils import *
12+
from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase
13+
from lldbsuite.test import lldbutil
14+
15+
16+
class TestConnectRemoteDetach(GDBRemoteTestBase):
17+
"""Test that ConnectRemote properly sets ShouldDetach flag."""
18+
19+
class StoppedResponder(MockGDBServerResponder):
20+
"""A responder that returns a stopped process."""
21+
22+
def qfThreadInfo(self):
23+
return "m1"
24+
25+
def qsThreadInfo(self):
26+
return "l"
27+
28+
def qC(self):
29+
return "QC1"
30+
31+
def haltReason(self):
32+
# Return that we're stopped
33+
return "T05thread:1;"
34+
35+
def cont(self):
36+
# Stay stopped
37+
return "T05thread:1;"
38+
39+
def D(self):
40+
# Detach packet: this is what we want to verify gets called.
41+
return "OK"
42+
43+
def k(self):
44+
# Kill packet: this is what we want to verify doesn't get called.
45+
raise RuntimeError("should not receive k(ill) packet")
46+
47+
def test_connect_remote_sets_detach(self):
48+
"""Test that ConnectRemote to a stopped process sets ShouldDetach."""
49+
self.server.responder = self.StoppedResponder()
50+
51+
target = self.createTarget("a.yaml")
52+
process = self.connect(target)
53+
54+
# Wait for the process to be in stopped state after connecting.
55+
# When ConnectRemote connects to a remote process that is stopped,
56+
# it should call SetShouldDetach(true) before CompleteAttach().
57+
lldbutil.expect_state_changes(
58+
self, self.dbg.GetListener(), process, [lldb.eStateStopped]
59+
)
60+
61+
# Now destroy the process. Because ShouldDetach was set to true
62+
# during ConnectRemote, this should send a 'D' (detach) packet
63+
# rather than a 'k' (kill) packet when the process is destroyed.
64+
process.Destroy()
65+
66+
# Verify that the (D)etach packet was sent.
67+
self.assertPacketLogReceived(["D"])

0 commit comments

Comments
 (0)