diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py @@ -239,14 +239,16 @@ def attach(self, program=None, pid=None, waitFor=None, trace=None, initCommands=None, preRunCommands=None, stopCommands=None, - exitCommands=None, attachCommands=None, coreFile=None): + exitCommands=None, attachCommands=None, terminateCommands=None, + coreFile=None, disconnect=True): '''Build the default Makefile target, create the VSCode debug adaptor, and attach to the process. ''' # Make sure we disconnect and terminate the VSCode debug adaptor even # if we throw an exception during the test case. def cleanup(): - self.vscode.request_disconnect(terminateDebuggee=True) + if disconnect: + self.vscode.request_disconnect(terminateDebuggee=True) self.vscode.terminate() # Execute the cleanup function during test case tear down. @@ -257,7 +259,8 @@ program=program, pid=pid, waitFor=waitFor, trace=trace, initCommands=initCommands, preRunCommands=preRunCommands, stopCommands=stopCommands, exitCommands=exitCommands, - attachCommands=attachCommands, coreFile=coreFile) + attachCommands=attachCommands, terminateCommands=terminateCommands, + coreFile=coreFile) if not (response and response['success']): self.assertTrue(response['success'], 'attach failed (%s)' % (response['message'])) @@ -266,15 +269,17 @@ stopOnEntry=False, disableASLR=True, disableSTDIO=False, shellExpandArguments=False, trace=False, initCommands=None, preRunCommands=None, - stopCommands=None, exitCommands=None,sourcePath=None, - debuggerRoot=None, launchCommands=None, sourceMap=None): + stopCommands=None, exitCommands=None, terminateCommands=None, + sourcePath=None, debuggerRoot=None, launchCommands=None, + sourceMap=None, disconnect=True): '''Sending launch request to vscode ''' # Make sure we disconnect and terminate the VSCode debug adapter, # if we throw an exception during the test case def cleanup(): - self.vscode.request_disconnect(terminateDebuggee=True) + if disconnect: + self.vscode.request_disconnect(terminateDebuggee=True) self.vscode.terminate() # Execute the cleanup function during test case tear down. @@ -296,6 +301,7 @@ preRunCommands=preRunCommands, stopCommands=stopCommands, exitCommands=exitCommands, + terminateCommands=terminateCommands, sourcePath=sourcePath, debuggerRoot=debuggerRoot, launchCommands=launchCommands, @@ -309,7 +315,8 @@ disableSTDIO=False, shellExpandArguments=False, trace=False, initCommands=None, preRunCommands=None, stopCommands=None, exitCommands=None, - sourcePath=None, debuggerRoot=None): + terminateCommands=None, sourcePath=None, + debuggerRoot=None, disconnect=False): '''Build the default Makefile target, create the VSCode debug adaptor, and launch the process. ''' @@ -319,4 +326,4 @@ self.launch(program, args, cwd, env, stopOnEntry, disableASLR, disableSTDIO, shellExpandArguments, trace, initCommands, preRunCommands, stopCommands, exitCommands, - sourcePath, debuggerRoot) + terminateCommands, sourcePath, debuggerRoot, disconnect) diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py @@ -450,7 +450,8 @@ def request_attach(self, program=None, pid=None, waitFor=None, trace=None, initCommands=None, preRunCommands=None, stopCommands=None, exitCommands=None, - attachCommands=None, coreFile=None): + attachCommands=None, terminateCommands=None, + coreFile=None): args_dict = {} if pid is not None: args_dict['pid'] = pid @@ -469,6 +470,8 @@ args_dict['stopCommands'] = stopCommands if exitCommands: args_dict['exitCommands'] = exitCommands + if terminateCommands: + args_dict['terminateCommands'] = terminateCommands if attachCommands: args_dict['attachCommands'] = attachCommands if coreFile: @@ -571,7 +574,8 @@ stopOnEntry=False, disableASLR=True, disableSTDIO=False, shellExpandArguments=False, trace=False, initCommands=None, preRunCommands=None, - stopCommands=None, exitCommands=None, sourcePath=None, + stopCommands=None, exitCommands=None, + terminateCommands=None ,sourcePath=None, debuggerRoot=None, launchCommands=None, sourceMap=None): args_dict = { 'program': program @@ -601,6 +605,8 @@ args_dict['stopCommands'] = stopCommands if exitCommands: args_dict['exitCommands'] = exitCommands + if terminateCommands: + args_dict['terminateCommands'] = terminateCommands if sourcePath: args_dict['sourcePath'] = sourcePath if debuggerRoot: @@ -905,7 +911,8 @@ initCommands=options.initCmds, preRunCommands=options.preRunCmds, stopCommands=options.stopCmds, - exitCommands=options.exitCmds) + exitCommands=options.exitCmds, + terminateCommands=options.terminateCmds) else: response = dbg.request_launch(options.program, args=args, @@ -916,7 +923,8 @@ initCommands=options.initCmds, preRunCommands=options.preRunCmds, stopCommands=options.stopCmds, - exitCommands=options.exitCmds) + exitCommands=options.exitCmds, + terminateCommands=options.terminateCmds) if response['success']: if options.sourceBreakpoints: @@ -1090,6 +1098,15 @@ 'exits. Can be specified more than once.')) parser.add_option( + '--terminateCommand', + type='string', + action='append', + dest='terminateCmds', + default=[], + help=('Specify a LLDB command that will be executed when the debugging ' + 'session is terminated. Can be specified more than once.')) + + parser.add_option( '--env', type='string', action='append', diff --git a/lldb/test/API/tools/lldb-vscode/attach/TestVSCode_attach.py b/lldb/test/API/tools/lldb-vscode/attach/TestVSCode_attach.py --- a/lldb/test/API/tools/lldb-vscode/attach/TestVSCode_attach.py +++ b/lldb/test/API/tools/lldb-vscode/attach/TestVSCode_attach.py @@ -46,6 +46,7 @@ @skipIfWindows @skipIfNetBSD # Hangs on NetBSD as well + @skipIfDarwin @skipIfRemote def test_by_pid(self): ''' @@ -63,6 +64,7 @@ @skipIfWindows @skipIfNetBSD # Hangs on NetBSD as well @skipIfRemote + @skipIfDarwin def test_by_name(self): ''' Tests attaching to a process by process name. @@ -121,8 +123,8 @@ def test_commands(self): ''' Tests the "initCommands", "preRunCommands", "stopCommands", - "exitCommands", and "attachCommands" that can be passed during - attach. + "exitCommands", "terminateCommands" and "attachCommands" + that can be passed during attach. "initCommands" are a list of LLDB commands that get executed before the targt is created. @@ -136,6 +138,8 @@ must have a valid process in the selected target in LLDB after they are done executing. This allows custom commands to create any kind of debug session. + "terminateCommands" are a list of LLDB commands that get executed when + the debugger session terminates. ''' self.build_and_create_debug_adaptor() program = self.getBuildArtifact("a.out") @@ -150,13 +154,15 @@ preRunCommands = ['image list a.out', 'image dump sections a.out'] stopCommands = ['frame variable', 'bt'] exitCommands = ['expr 2+3', 'expr 3+4'] + terminateCommands = ['expr 4+2'] self.attach(program=program, attachCommands=attachCommands, initCommands=initCommands, preRunCommands=preRunCommands, stopCommands=stopCommands, - exitCommands=exitCommands) - + exitCommands=exitCommands, + terminateCommands=terminateCommands, + disconnect=False) # Get output from the console. This should contain both the # "initCommands" and the "preRunCommands". output = self.get_console() @@ -189,3 +195,8 @@ # "exitCommands" that were run after the second breakpoint was hit output = self.get_console(timeout=1.0) self.verify_commands('exitCommands', output, exitCommands) + # Once it's disconnected the console should contain the + # "terminateCommands" + self.vscode.request_disconnect(terminateDebuggee=True) + output = self.get_console(timeout=1.0) + self.verify_commands('terminateCommands', output, terminateCommands) diff --git a/lldb/test/API/tools/lldb-vscode/launch/TestVSCode_launch.py b/lldb/test/API/tools/lldb-vscode/launch/TestVSCode_launch.py --- a/lldb/test/API/tools/lldb-vscode/launch/TestVSCode_launch.py +++ b/lldb/test/API/tools/lldb-vscode/launch/TestVSCode_launch.py @@ -294,8 +294,9 @@ @skipIfRemote def test_commands(self): ''' - Tests the "initCommands", "preRunCommands", "stopCommands" and - "exitCommands" that can be passed during launch. + Tests the "initCommands", "preRunCommands", "stopCommands", + "terminateCommands" and "exitCommands" that can be passed during + launch. "initCommands" are a list of LLDB commands that get executed before the targt is created. @@ -305,17 +306,22 @@ time the program stops. "exitCommands" are a list of LLDB commands that get executed when the process exits + "terminateCommands" are a list of LLDB commands that get executed when + the debugger session terminates. ''' program = self.getBuildArtifact("a.out") initCommands = ['target list', 'platform list'] preRunCommands = ['image list a.out', 'image dump sections a.out'] stopCommands = ['frame variable', 'bt'] exitCommands = ['expr 2+3', 'expr 3+4'] + terminateCommands = ['expr 4+2'] self.build_and_launch(program, initCommands=initCommands, preRunCommands=preRunCommands, stopCommands=stopCommands, - exitCommands=exitCommands) + exitCommands=exitCommands, + terminateCommands=terminateCommands, + disconnect=False) # Get output from the console. This should contain both the # "initCommands" and the "preRunCommands". @@ -356,6 +362,11 @@ # "exitCommands" that were run after the second breakpoint was hit output = self.get_console(timeout=1.0) self.verify_commands('exitCommands', output, exitCommands) + # Once it's disconnected the console should contain the + # "terminateCommands" + self.vscode.request_disconnect(terminateDebuggee=True) + output = self.get_console(timeout=1.0) + self.verify_commands('terminateCommands', output, terminateCommands) @skipIfWindows @skipIfRemote diff --git a/lldb/tools/lldb-vscode/VSCode.h b/lldb/tools/lldb-vscode/VSCode.h --- a/lldb/tools/lldb-vscode/VSCode.h +++ b/lldb/tools/lldb-vscode/VSCode.h @@ -86,6 +86,7 @@ std::vector pre_run_commands; std::vector exit_commands; std::vector stop_commands; + std::vector terminate_commands; lldb::tid_t focus_tid; bool sent_terminated_event; bool stop_at_entry; @@ -132,6 +133,7 @@ void RunPreRunCommands(); void RunStopCommands(); void RunExitCommands(); + void RunTerminateCommands(); /// Create a new SBTarget object from the given request arguments. /// \param[in] arguments diff --git a/lldb/tools/lldb-vscode/VSCode.cpp b/lldb/tools/lldb-vscode/VSCode.cpp --- a/lldb/tools/lldb-vscode/VSCode.cpp +++ b/lldb/tools/lldb-vscode/VSCode.cpp @@ -309,6 +309,10 @@ RunLLDBCommands("Running exitCommands:", exit_commands); } +void VSCode::RunTerminateCommands() { + RunLLDBCommands("Running terminateCommands:", terminate_commands); +} + lldb::SBTarget VSCode::CreateTargetFromArguments( const llvm::json::Object &arguments, lldb::SBError &error) { diff --git a/lldb/tools/lldb-vscode/lldb-vscode.cpp b/lldb/tools/lldb-vscode/lldb-vscode.cpp --- a/lldb/tools/lldb-vscode/lldb-vscode.cpp +++ b/lldb/tools/lldb-vscode/lldb-vscode.cpp @@ -396,6 +396,7 @@ // launch.json g_vsc.RunExitCommands(); SendProcessExitedEvent(process); + g_vsc.RunTerminateCommands(); SendTerminatedEvent(); done = true; } break; @@ -529,6 +530,7 @@ g_vsc.pre_run_commands = GetStrings(arguments, "preRunCommands"); g_vsc.stop_commands = GetStrings(arguments, "stopCommands"); g_vsc.exit_commands = GetStrings(arguments, "exitCommands"); + g_vsc.terminate_commands = GetStrings(arguments, "terminateCommands"); auto attachCommands = GetStrings(arguments, "attachCommands"); llvm::StringRef core_file = GetString(arguments, "coreFile"); g_vsc.stop_at_entry = @@ -772,7 +774,7 @@ bool terminateDebuggee = GetBoolean(arguments, "terminateDebuggee", false); lldb::SBProcess process = g_vsc.target.GetProcess(); auto state = process.GetState(); - + g_vsc.RunTerminateCommands(); switch (state) { case lldb::eStateInvalid: case lldb::eStateUnloaded: @@ -1365,6 +1367,7 @@ g_vsc.pre_run_commands = GetStrings(arguments, "preRunCommands"); g_vsc.stop_commands = GetStrings(arguments, "stopCommands"); g_vsc.exit_commands = GetStrings(arguments, "exitCommands"); + g_vsc.terminate_commands = GetStrings(arguments, "terminateCommands"); auto launchCommands = GetStrings(arguments, "launchCommands"); g_vsc.stop_at_entry = GetBoolean(arguments, "stopOnEntry", false); const llvm::StringRef debuggerRoot = GetString(arguments, "debuggerRoot");