Skip to content

Commit

Permalink
Fix #1217: Support "restart" in "terminated" event for "attach"{"list…
Browse files Browse the repository at this point in the history
…en"}

Request client to restart the adapter if "restart":true was specified in the debug configuration.
  • Loading branch information
Pavel Minaev authored and int19h committed Feb 27, 2023
1 parent e9dc3e8 commit 5601342
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 3 deletions.
1 change: 1 addition & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"host": "127.0.0.1"
},
"logToFile": true,
//"restart": true,
"debugAdapterPath": "${workspaceFolder}/src/debugpy/adapter"
},
{
Expand Down
34 changes: 32 additions & 2 deletions src/debugpy/adapter/clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class Expectations(components.Capabilities):
def __init__(self, sock):
if sock == "stdio":
log.info("Connecting to client over stdio...", self)
self.using_stdio = True
stream = messaging.JsonIOStream.from_stdio()
# Make sure that nothing else tries to interfere with the stdio streams
# that are going to be used for DAP communication from now on.
Expand All @@ -52,6 +53,7 @@ def __init__(self, sock):
sys.stdout = stdout = open(os.devnull, "w")
atexit.register(stdout.close)
else:
self.using_stdio = False
stream = messaging.JsonIOStream.from_socket(sock)

with sessions.Session() as session:
Expand All @@ -69,6 +71,11 @@ def __init__(self, sock):
"""The "launch" or "attach" request as received from the client.
"""

self.restart_requested = False
"""Whether the client requested the debug adapter to be automatically
restarted via "restart":true in the start request.
"""

self._initialize_request = None
"""The "initialize" request as received from the client, to propagate to the
server later."""
Expand Down Expand Up @@ -471,6 +478,7 @@ def attach_request(self, request):
host = listen("host", "127.0.0.1")
port = listen("port", int)
adapter.access_token = None
self.restart_requested = request("restart", False)
host, port = servers.serve(host, port)
else:
if not servers.is_serving():
Expand Down Expand Up @@ -651,6 +659,10 @@ def debugpySystemInfo_request(self, request):

@message_handler
def terminate_request(self, request):
# If user specifically requests to terminate, it means that they don't want
# debug session auto-restart kicking in.
self.restart_requested = False

if self._forward_terminate_request:
# According to the spec, terminate should try to do a gracefull shutdown.
# We do this in the server by interrupting the main thread with a Ctrl+C.
Expand All @@ -665,11 +677,29 @@ def terminate_request(self, request):

@message_handler
def disconnect_request(self, request):
# If user specifically requests to disconnect, it means that they don't want
# debug session auto-restart kicking in.
self.restart_requested = False

terminate_debuggee = request("terminateDebuggee", bool, optional=True)
if terminate_debuggee == ():
terminate_debuggee = None
self.session.finalize('client requested "disconnect"', terminate_debuggee)
return {}
request.respond({})

if self.using_stdio:
# There's no way for the client to reconnect to this adapter once it disconnects
# from this session, so close any remaining server connections.
servers.stop_serving()
log.info("{0} disconnected from stdio; closing remaining server connections.", self)
for conn in servers.connections():
try:
conn.channel.close()
except Exception:
log.swallow_exception()

def disconnect(self):
super().disconnect()

def notify_of_subprocess(self, conn):
log.info("{1} is a subprocess of {0}.", self, conn)
Expand All @@ -689,7 +719,7 @@ def notify_of_subprocess(self, conn):
self.known_subprocesses.add(conn)
self.session.notify_changed()

for key in "processId", "listen", "preLaunchTask", "postDebugTask", "request":
for key in "processId", "listen", "preLaunchTask", "postDebugTask", "request", "restart":
body.pop(key, None)

body["name"] = "Subprocess {0}".format(conn.pid)
Expand Down
5 changes: 4 additions & 1 deletion src/debugpy/adapter/sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,11 @@ def _finalize(self, why, terminate_debuggee):
if self.client.is_connected:
# Tell the client that debugging is over, but don't close the channel until it
# tells us to, via the "disconnect" request.
body = {}
if self.client.restart_requested:
body["restart"] = True
try:
self.client.channel.send_event("terminated")
self.client.channel.send_event("terminated", body)
except Exception:
pass

Expand Down
1 change: 1 addition & 0 deletions src/debugpy/common/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ def report_paths(get_paths, label=None):
prefix = " " * len(prefix)

report("System paths:\n")
report_paths("sys.executable")
report_paths("sys.prefix")
report_paths("sys.base_prefix")
report_paths("sys.real_prefix")
Expand Down

0 comments on commit 5601342

Please sign in to comment.