@@ -44,6 +44,7 @@ class Expectations(components.Capabilities):
44
44
def __init__ (self , sock ):
45
45
if sock == "stdio" :
46
46
log .info ("Connecting to client over stdio..." , self )
47
+ self .using_stdio = True
47
48
stream = messaging .JsonIOStream .from_stdio ()
48
49
# Make sure that nothing else tries to interfere with the stdio streams
49
50
# that are going to be used for DAP communication from now on.
@@ -52,6 +53,7 @@ def __init__(self, sock):
52
53
sys .stdout = stdout = open (os .devnull , "w" )
53
54
atexit .register (stdout .close )
54
55
else :
56
+ self .using_stdio = False
55
57
stream = messaging .JsonIOStream .from_socket (sock )
56
58
57
59
with sessions .Session () as session :
@@ -69,6 +71,11 @@ def __init__(self, sock):
69
71
"""The "launch" or "attach" request as received from the client.
70
72
"""
71
73
74
+ self .restart_requested = False
75
+ """Whether the client requested the debug adapter to be automatically
76
+ restarted via "restart":true in the start request.
77
+ """
78
+
72
79
self ._initialize_request = None
73
80
"""The "initialize" request as received from the client, to propagate to the
74
81
server later."""
@@ -471,6 +478,7 @@ def attach_request(self, request):
471
478
host = listen ("host" , "127.0.0.1" )
472
479
port = listen ("port" , int )
473
480
adapter .access_token = None
481
+ self .restart_requested = request ("restart" , False )
474
482
host , port = servers .serve (host , port )
475
483
else :
476
484
if not servers .is_serving ():
@@ -651,6 +659,10 @@ def debugpySystemInfo_request(self, request):
651
659
652
660
@message_handler
653
661
def terminate_request (self , request ):
662
+ # If user specifically requests to terminate, it means that they don't want
663
+ # debug session auto-restart kicking in.
664
+ self .restart_requested = False
665
+
654
666
if self ._forward_terminate_request :
655
667
# According to the spec, terminate should try to do a gracefull shutdown.
656
668
# We do this in the server by interrupting the main thread with a Ctrl+C.
@@ -665,11 +677,29 @@ def terminate_request(self, request):
665
677
666
678
@message_handler
667
679
def disconnect_request (self , request ):
680
+ # If user specifically requests to disconnect, it means that they don't want
681
+ # debug session auto-restart kicking in.
682
+ self .restart_requested = False
683
+
668
684
terminate_debuggee = request ("terminateDebuggee" , bool , optional = True )
669
685
if terminate_debuggee == ():
670
686
terminate_debuggee = None
671
687
self .session .finalize ('client requested "disconnect"' , terminate_debuggee )
672
- return {}
688
+ request .respond ({})
689
+
690
+ if self .using_stdio :
691
+ # There's no way for the client to reconnect to this adapter once it disconnects
692
+ # from this session, so close any remaining server connections.
693
+ servers .stop_serving ()
694
+ log .info ("{0} disconnected from stdio; closing remaining server connections." , self )
695
+ for conn in servers .connections ():
696
+ try :
697
+ conn .channel .close ()
698
+ except Exception :
699
+ log .swallow_exception ()
700
+
701
+ def disconnect (self ):
702
+ super ().disconnect ()
673
703
674
704
def notify_of_subprocess (self , conn ):
675
705
log .info ("{1} is a subprocess of {0}." , self , conn )
@@ -689,7 +719,7 @@ def notify_of_subprocess(self, conn):
689
719
self .known_subprocesses .add (conn )
690
720
self .session .notify_changed ()
691
721
692
- for key in "processId" , "listen" , "preLaunchTask" , "postDebugTask" , "request" :
722
+ for key in "processId" , "listen" , "preLaunchTask" , "postDebugTask" , "request" , "restart" :
693
723
body .pop (key , None )
694
724
695
725
body ["name" ] = "Subprocess {0}" .format (conn .pid )
0 commit comments