Skip to content

Commit 58d1618

Browse files
zyn-likusmour
authored andcommitted
[lldb-dap] bug-fix: lldb-dap remembered old sessionId when reused
Summary: Context: lldb-dap remembers the vscode session id in its lifecycle, the new session id when reuse lldb-dap didn't get updated in lldb-dap. This diff is aiming to fix such issue on the lldb-dap side. Approach: fetching `__sessionId` key from attach & launch request, and update the env value by inserting new initCommands. Test Plan: Added new test case to test the env value update in lldb-dap to run the test case: ~/local/llvm-sand/build/Debug/fbcode-x86_64/toolchain/bin/lldb-dotest -p <PATH_TO_TEST>/TestDAP_launch.py ^ replace path to the local build lldb-dotest. ^ [lldb-dotest](https://www.internalfb.com/wiki/SaND/Developing_LLDB) Attach Test cases results: P1754726175 Launch Test Cases results: P1754738053 reuseDap Test Cases results: P1754757203 Reviewers: jeffreytan, royshi, gclayton, #lldb_team Reviewed By: jeffreytan, royshi Subscribers: royshi Differential Revision: https://phabricator.intern.facebook.com/D70663297 Tasks: T215634007
1 parent 5f2b6b4 commit 58d1618

File tree

10 files changed

+184
-4
lines changed

10 files changed

+184
-4
lines changed

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,7 @@ def request_attach(
697697
sourceMap: Optional[Union[list[tuple[str, str]], dict[str, str]]] = None,
698698
gdbRemotePort: Optional[int] = None,
699699
gdbRemoteHostname: Optional[str] = None,
700+
vscode_session_id=None,
700701
):
701702
args_dict = {}
702703
if pid is not None:
@@ -730,6 +731,9 @@ def request_attach(
730731
args_dict["gdb-remote-port"] = gdbRemotePort
731732
if gdbRemoteHostname is not None:
732733
args_dict["gdb-remote-hostname"] = gdbRemoteHostname
734+
if vscode_session_id:
735+
args_dict["__sessionId"] = vscode_session_id
736+
733737
command_dict = {"command": "attach", "type": "request", "arguments": args_dict}
734738
return self.send_recv(command_dict)
735739

@@ -939,6 +943,7 @@ def request_launch(
939943
commandEscapePrefix: Optional[str] = None,
940944
customFrameFormat: Optional[str] = None,
941945
customThreadFormat: Optional[str] = None,
946+
vscode_session_id=None,
942947
):
943948
args_dict = {"program": program}
944949
if args:
@@ -980,6 +985,8 @@ def request_launch(
980985
args_dict["customFrameFormat"] = customFrameFormat
981986
if customThreadFormat:
982987
args_dict["customThreadFormat"] = customThreadFormat
988+
if vscode_session_id:
989+
args_dict["__sessionId"] = vscode_session_id
983990

984991
args_dict["disableASLR"] = disableASLR
985992
args_dict["enableAutoVariableSummaries"] = enableAutoVariableSummaries

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

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,45 @@ def test_terminate_commands(self):
227227
pattern=terminateCommands[0],
228228
)
229229
self.verify_commands("terminateCommands", output, terminateCommands)
230+
231+
def test_session_id_update(self):
232+
self.build_and_create_debug_adapter()
233+
program = self.getBuildArtifact("a.out")
234+
235+
def spawn(program):
236+
process = subprocess.Popen(
237+
[program], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE
238+
)
239+
self.spawn_thread = threading.Thread(
240+
target=spawn,
241+
args=(program,),
242+
)
243+
self.spawn_thread.start()
244+
postRunCommands = ["script print('Actual_Session_ID: ' + str(os.getenv('VSCODE_DEBUG_SESSION_ID')))"]
245+
self.attach(program=program, vscode_session_id="test_session_id", postRunCommands=postRunCommands)
246+
output = self.get_console()
247+
lines = filter(lambda x: 'Actual_Session_ID' in x, output.splitlines())
248+
self.assertTrue(
249+
any('test_session_id' in l for l in lines), "expect session id in console output"
250+
)
251+
252+
def test_session_id_update_empty(self):
253+
self.build_and_create_debug_adapter()
254+
program = self.getBuildArtifact("a.out")
255+
256+
def spawn(program):
257+
process = subprocess.Popen(
258+
[program], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE
259+
)
260+
self.spawn_thread = threading.Thread(
261+
target=spawn,
262+
args=(program,),
263+
)
264+
self.spawn_thread.start()
265+
postRunCommands = ["script print('Actual_Session_ID: ' + str(os.getenv('VSCODE_DEBUG_SESSION_ID', 'None')))"]
266+
self.attach(program=program, postRunCommands=postRunCommands)
267+
output = self.get_console()
268+
lines = filter(lambda x: 'Actual_Session_ID' in x, output.splitlines())
269+
self.assertTrue(
270+
any(l == "Actual_Session_ID: None" in l for l in lines), "expect session id in console output"
271+
)

lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,3 +572,28 @@ def test_version(self):
572572
version_string.splitlines(),
573573
"version string does not match",
574574
)
575+
576+
def test_session_id_update(self):
577+
program = self.getBuildArtifact("a.out")
578+
postRunCommands = ["script print('Actual_Session_ID: ' + str(os.getenv('VSCODE_DEBUG_SESSION_ID')))"]
579+
self.build_and_launch(
580+
program,
581+
vscode_session_id="test_session_id",
582+
postRunCommands=postRunCommands,
583+
)
584+
output = self.get_console()
585+
self.continue_to_exit()
586+
lines = filter(lambda x: 'Actual_Session_ID' in x, output.splitlines())
587+
self.assertTrue(
588+
any("test_session_id" in l for l in lines), "expect session id in console output"
589+
)
590+
591+
def test_session_id_update_empty(self):
592+
program = self.getBuildArtifact("a.out")
593+
self.build_and_launch(program)
594+
output = self.get_console()
595+
self.continue_to_exit()
596+
self.assertTrue(
597+
all("VSCODE_DEBUG_SESSION_ID" not in l for l in output.splitlines()),
598+
"expect NO session id update command"
599+
)

lldb/test/API/tools/lldb-dap/reuseDAP/TestDAP_reuseAdapter.py

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import os
1212

1313

14-
class TestDAP_reuseAdpater(lldbdap_testcase.DAPTestCaseBase):
14+
class TestDAP_reuseAdapter(lldbdap_testcase.DAPTestCaseBase):
1515
@skipIfWindows
1616
def test_basic_reuse(self):
1717
"""
@@ -20,7 +20,7 @@ def test_basic_reuse(self):
2020
program = self.getBuildArtifact("a.out")
2121

2222
# Keep lldb-dap alive for 10 minutes.
23-
dapKeepAliveTimeInMS = 10 * 1000 * 60
23+
dapKeepAliveTimeInMS = 10 * 1000 * 60
2424
self.build_and_launch(program, disconnectAutomatically=False, keepAliveTimeout=dapKeepAliveTimeInMS)
2525

2626
source = "main.cpp"
@@ -32,7 +32,7 @@ def test_basic_reuse(self):
3232
# Second debug session by reusing lldb-dap.
3333
self.create_debug_adapter(reuseDapServer=True)
3434
self.launch(program)
35-
35+
3636
breakpoint2_line = line_number(source, "// breakpoint 2")
3737
breakpoint_ids = self.set_source_breakpoints(source, [breakpoint2_line])
3838
self.continue_to_breakpoints(breakpoint_ids)
@@ -68,3 +68,45 @@ def test_exception_breakopints(self):
6868
self.assertTrue(response["success"])
6969
self.continue_to_exception_breakpoint("C++ Throw")
7070
self.dap_server.request_disconnect()
71+
72+
def test_session_id_update_when_reuse(self):
73+
"""
74+
Test if vscode session id being updated when lldb-dap reused
75+
"""
76+
# Add set up command to print out the session id, with a unique identifier as prefix
77+
program = self.getBuildArtifact("a.out")
78+
postRunCommands = ["script print('Actual_Session_ID: ' + str(os.getenv('VSCODE_DEBUG_SESSION_ID')))"]
79+
80+
# Keep lldb-dap alive for 10 minutes.
81+
dapKeepAliveTimeInMS = 10 * 1000 * 60
82+
self.build_and_launch(
83+
program,
84+
vscode_session_id="test_session_id",
85+
postRunCommands=postRunCommands,
86+
disconnectAutomatically=False,
87+
keepAliveTimeout=dapKeepAliveTimeInMS
88+
)
89+
90+
# Validate the session id in the inital launch of lldb-dap
91+
output = self.get_console()
92+
lines = filter(lambda x: 'Actual_Session_ID' in x, output.splitlines())
93+
self.assertTrue(
94+
any("test_session_id" in l for l in lines), "expect session id in console output"
95+
)
96+
self.dap_server.request_disconnect()
97+
98+
# Second debug session by reusing lldb-dap.
99+
self.create_debug_adapter(reuseDapServer=True)
100+
self.launch(
101+
program,
102+
vscode_session_id="NEW_session_id",
103+
postRunCommands=postRunCommands
104+
)
105+
106+
# Validate the updated session id in the reused lldb-dap
107+
output = self.get_console()
108+
lines = filter(lambda x: 'Actual_Session_ID' in x, output.splitlines())
109+
self.assertTrue(
110+
any("NEW_session_id" in l for l in lines), "expect new session id in console output"
111+
)
112+
self.dap_server.request_disconnect()

lldb/tools/lldb-dap/Handler/AttachRequestHandler.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ Error AttachRequestHandler::Run(const AttachRequestArguments &args) const {
4848
if (!args.coreFile.empty())
4949
dap.stop_at_entry = true;
5050

51+
// When lldb-dap is reused, the ID of each session is passed in by a request
52+
// argument, rather than through the environment variable. Set it into the
53+
// environment variable, so that the downstream code can pick it up from there.
54+
// See T215634007 for more details.
55+
UpdateVSCodeSessionID(args, dap);
56+
5157
PrintWelcomeMessage();
5258

5359
// This is a hack for loading DWARF in .o files on Mac where the .o files

lldb/tools/lldb-dap/Handler/LaunchRequestHandler.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ Error LaunchRequestHandler::Run(const LaunchRequestArguments &arguments) const {
3030
dap.SetConfiguration(arguments.configuration, /*is_attach=*/false);
3131
dap.last_launch_request = arguments;
3232

33+
// When lldb-dap is reused, the ID of each session is passed in by a request
34+
// argument, rather than through the environment variable. Set it into the
35+
// environment variable, so that the downstream code can pick it up from there.
36+
// See T215634007 for more details.
37+
UpdateVSCodeSessionID(arguments, dap);
38+
3339
PrintWelcomeMessage();
3440

3541
// This is a hack for loading DWARF in .o files on Mac where the .o files

lldb/tools/lldb-dap/LLDBUtils.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "LLDBUtils.h"
10+
#include "DAP.h"
1011
#include "JSONUtils.h"
1112
#include "lldb/API/SBCommandInterpreter.h"
1213
#include "lldb/API/SBCommandReturnObject.h"
@@ -19,6 +20,7 @@
1920
#include "llvm/ADT/ArrayRef.h"
2021
#include "llvm/Support/JSON.h"
2122
#include "llvm/Support/raw_ostream.h"
23+
#include "Protocol/ProtocolRequests.h"
2224

2325
#include <cstring>
2426
#include <mutex>
@@ -259,4 +261,20 @@ lldb::SBLineEntry GetLineEntryForAddress(lldb::SBTarget &target,
259261
return sc.GetLineEntry();
260262
}
261263

264+
void UpdateVSCodeSessionID(const protocol::LaunchRequestArguments arguments, DAP &dap) {
265+
if (!arguments.__sessionId.has_value() || arguments.__sessionId->empty())
266+
return; // No session ID provided.
267+
dap.configuration.initCommands.insert(
268+
dap.configuration.initCommands.begin(),
269+
"script os.environ['VSCODE_DEBUG_SESSION_ID'] = '" + *arguments.__sessionId + "'");
270+
}
271+
272+
void UpdateVSCodeSessionID(const protocol::AttachRequestArguments arguments, DAP &dap) {
273+
if (!arguments.__sessionId.has_value() || arguments.__sessionId->empty())
274+
return; // No session ID provided.
275+
dap.configuration.initCommands.insert(
276+
dap.configuration.initCommands.begin(),
277+
"script os.environ['VSCODE_DEBUG_SESSION_ID'] = '" + *arguments.__sessionId + "'");
278+
}
279+
262280
} // namespace lldb_dap

lldb/tools/lldb-dap/LLDBUtils.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "llvm/Support/JSON.h"
2323
#include "llvm/Support/ScopedPrinter.h"
2424
#include "llvm/Support/raw_ostream.h"
25+
#include "Protocol/ProtocolRequests.h"
2526
#include <chrono>
2627
#include <string>
2728

@@ -248,6 +249,31 @@ llvm::Error ToError(const lldb::SBError &error);
248249
/// Provides the string value if this data structure is a string type.
249250
std::string GetStringValue(const lldb::SBStructuredData &data);
250251

252+
/// Get the vscode session id from the request arguments.
253+
/// If exists, insert the fetched session id into dap init_commands.
254+
///
255+
/// \param[in] arguments
256+
/// The LaunchRequestArguments
257+
///
258+
/// \param[in] dap
259+
/// The DAP session
260+
///
261+
/// \return
262+
/// void
263+
void UpdateVSCodeSessionID(const protocol::LaunchRequestArguments arguments, DAP &dap);
264+
265+
/// Get the vscode session id from the request arguments.
266+
/// If exists, insert the fetched session id into dap init_commands.
267+
///
268+
/// \param[in] arguments
269+
/// The AttachRequestArguments
270+
///
271+
/// \param[in] dap
272+
/// The DAP session
273+
///
274+
/// \return
275+
/// void
276+
void UpdateVSCodeSessionID(const protocol::AttachRequestArguments arguments, DAP &dap);
251277
} // namespace lldb_dap
252278

253279
#endif

lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ bool fromJSON(const json::Value &Params, LaunchRequestArguments &LRA,
277277
O.mapOptional("shellExpandArguments", LRA.shellExpandArguments) &&
278278

279279
O.mapOptional("runInTerminal", LRA.runInTerminal) &&
280+
O.mapOptional("__sessionId", LRA.__sessionId) &&
280281
parseEnv(Params, LRA.env, P);
281282
}
282283

@@ -289,7 +290,8 @@ bool fromJSON(const json::Value &Params, AttachRequestArguments &ARA,
289290
O.mapOptional("waitFor", ARA.waitFor) &&
290291
O.mapOptional("gdb-remote-port", ARA.gdbRemotePort) &&
291292
O.mapOptional("gdb-remote-hostname", ARA.gdbRemoteHostname) &&
292-
O.mapOptional("coreFile", ARA.coreFile);
293+
O.mapOptional("coreFile", ARA.coreFile) &&
294+
O.mapOptional("__sessionId", ARA.__sessionId);
293295
}
294296

295297
bool fromJSON(const json::Value &Params, ContinueArguments &CA, json::Path P) {

lldb/tools/lldb-dap/Protocol/ProtocolRequests.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,9 @@ struct LaunchRequestArguments {
302302
/// debugging interactive command line programs.
303303
bool runInTerminal = false;
304304

305+
/// VSCode session ID for debugging session tracking.
306+
std::optional<std::string> __sessionId;
307+
305308
/// @}
306309
};
307310
bool fromJSON(const llvm::json::Value &, LaunchRequestArguments &,
@@ -347,6 +350,9 @@ struct AttachRequestArguments {
347350
/// Path to the core file to debug.
348351
std::string coreFile;
349352

353+
/// VSCode session ID for debugging session tracking.
354+
std::optional<std::string> __sessionId;
355+
350356
/// @}
351357
};
352358
bool fromJSON(const llvm::json::Value &, AttachRequestArguments &,

0 commit comments

Comments
 (0)