mirror of
https://github.com/microsoft/debugpy.git
synced 2025-12-23 08:48:12 +00:00
Fix #1074: Use "startDebugging" request for subprocesses
Use the request if client advertises the "supportsStartDebuggingRequest" capability.
This commit is contained in:
parent
9fd3e72235
commit
e9dc3e8844
3 changed files with 52 additions and 20 deletions
|
|
@ -30,6 +30,7 @@ class Client(components.Component):
|
|||
"supportsRunInTerminalRequest": False,
|
||||
"supportsMemoryReferences": False,
|
||||
"supportsArgsCanBeInterpretedByShell": False,
|
||||
"supportsStartDebuggingRequest": False,
|
||||
}
|
||||
|
||||
class Expectations(components.Capabilities):
|
||||
|
|
@ -688,11 +689,10 @@ class Client(components.Component):
|
|||
self.known_subprocesses.add(conn)
|
||||
self.session.notify_changed()
|
||||
|
||||
for key in "processId", "listen", "preLaunchTask", "postDebugTask":
|
||||
for key in "processId", "listen", "preLaunchTask", "postDebugTask", "request":
|
||||
body.pop(key, None)
|
||||
|
||||
body["name"] = "Subprocess {0}".format(conn.pid)
|
||||
body["request"] = "attach"
|
||||
body["subProcessId"] = conn.pid
|
||||
|
||||
for key in "args", "processName", "pythonArgs":
|
||||
|
|
@ -709,7 +709,14 @@ class Client(components.Component):
|
|||
_, port = listener.getsockname()
|
||||
body["connect"]["port"] = port
|
||||
|
||||
self.channel.send_event("debugpyAttach", body)
|
||||
if self.capabilities["supportsStartDebuggingRequest"]:
|
||||
self.channel.request("startDebugging", {
|
||||
"request": "attach",
|
||||
"configuration": body,
|
||||
})
|
||||
else:
|
||||
body["request"] = "attach"
|
||||
self.channel.send_event("debugpyAttach", body)
|
||||
|
||||
|
||||
def serve(host, port):
|
||||
|
|
|
|||
|
|
@ -84,6 +84,18 @@ class Session(object):
|
|||
|
||||
self.client_id = "vscode"
|
||||
|
||||
self.capabilities = {
|
||||
"pathFormat": "path",
|
||||
"clientID": self.client_id,
|
||||
"adapterID": "test",
|
||||
"linesStartAt1": True,
|
||||
"columnsStartAt1": True,
|
||||
"supportsVariableType": True,
|
||||
"supportsRunInTerminalRequest": True,
|
||||
"supportsArgsCanBeInterpretedByShell": True,
|
||||
"supportsStartDebuggingRequest": False,
|
||||
}
|
||||
|
||||
self.debuggee = None
|
||||
"""psutil.Popen instance for the debuggee process."""
|
||||
|
||||
|
|
@ -502,6 +514,10 @@ class Session(object):
|
|||
except Exception as exc:
|
||||
log.swallow_exception('"runInTerminal" failed:')
|
||||
raise request.cant_handle(str(exc))
|
||||
elif request.command == "startDebugging":
|
||||
pid = request("configuration", dict)("subProcessId", int)
|
||||
watchdog.register_spawn(pid, f"{self.debuggee_id}-subprocess-{pid}")
|
||||
return {}
|
||||
else:
|
||||
raise request.isnt_valid("not supported")
|
||||
|
||||
|
|
@ -551,19 +567,7 @@ class Session(object):
|
|||
)
|
||||
)
|
||||
|
||||
self.request(
|
||||
"initialize",
|
||||
{
|
||||
"pathFormat": "path",
|
||||
"clientID": self.client_id,
|
||||
"adapterID": "test",
|
||||
"linesStartAt1": True,
|
||||
"columnsStartAt1": True,
|
||||
"supportsVariableType": True,
|
||||
"supportsRunInTerminalRequest": True,
|
||||
"supportsArgsCanBeInterpretedByShell": True,
|
||||
},
|
||||
)
|
||||
self.request("initialize", self.capabilities)
|
||||
|
||||
def all_events(self, event, body=some.object):
|
||||
return [
|
||||
|
|
@ -783,7 +787,15 @@ class Session(object):
|
|||
return StopInfo(stopped, frames, tid, fid)
|
||||
|
||||
def wait_for_next_subprocess(self):
|
||||
return Session(self.wait_for_next_event("debugpyAttach"))
|
||||
message = self.timeline.wait_for_next(timeline.Event("debugpyAttach") | timeline.Request("startDebugging"))
|
||||
if isinstance(message, timeline.EventOccurrence):
|
||||
config = message.body
|
||||
assert "request" in config
|
||||
elif isinstance(message, timeline.RequestOccurrence):
|
||||
config = dict(message.body("configuration", dict))
|
||||
assert "request" not in config
|
||||
config["request"] = "attach"
|
||||
return Session(config)
|
||||
|
||||
def wait_for_disconnect(self):
|
||||
self.timeline.wait_until_realized(timeline.Mark("disconnect"), freeze=True)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import sys
|
|||
|
||||
import debugpy
|
||||
import tests
|
||||
from tests import debug, log
|
||||
from tests import debug, log, timeline
|
||||
from tests.debug import runners
|
||||
from tests.patterns import some
|
||||
|
||||
|
|
@ -151,7 +151,8 @@ def test_multiprocessing(pyfile, target, run, start_method):
|
|||
|
||||
|
||||
@pytest.mark.parametrize("subProcess", [True, False, None])
|
||||
def test_subprocess(pyfile, target, run, subProcess):
|
||||
@pytest.mark.parametrize("method", ["startDebugging", "debugpyAttach", ""])
|
||||
def test_subprocess(pyfile, target, run, subProcess, method):
|
||||
@pyfile
|
||||
def child():
|
||||
import os
|
||||
|
|
@ -188,6 +189,8 @@ def test_subprocess(pyfile, target, run, subProcess):
|
|||
with debug.Session() as parent_session:
|
||||
backchannel = parent_session.open_backchannel()
|
||||
|
||||
if method:
|
||||
parent_session.capabilities["supportsStartDebuggingRequest"] = (method == "startDebugging")
|
||||
parent_session.config["preLaunchTask"] = "doSomething"
|
||||
parent_session.config["postDebugTask"] = "doSomethingElse"
|
||||
if subProcess is not None:
|
||||
|
|
@ -200,9 +203,19 @@ def test_subprocess(pyfile, target, run, subProcess):
|
|||
return
|
||||
|
||||
expected_child_config = expected_subprocess_config(parent_session)
|
||||
child_config = parent_session.wait_for_next_event("debugpyAttach")
|
||||
|
||||
if method == "startDebugging":
|
||||
subprocess_request = parent_session.timeline.wait_for_next(timeline.Request("startDebugging"))
|
||||
child_config = subprocess_request.arguments("configuration", dict)
|
||||
del expected_child_config["request"]
|
||||
else:
|
||||
child_config = parent_session.wait_for_next_event("debugpyAttach")
|
||||
|
||||
child_config = dict(child_config)
|
||||
child_config.pop("isOutputRedirected", None)
|
||||
assert child_config == expected_child_config
|
||||
child_config["request"] = "attach"
|
||||
|
||||
parent_session.proceed()
|
||||
|
||||
with debug.Session(child_config) as child_session:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue