mirror of
https://github.com/microsoft/debugpy.git
synced 2025-12-23 08:48:12 +00:00
Send the disconnect response before closing the client socket. (#531)
(see #530) We were sending the "disconnect" response only after closing the socket, meaning the response was never actually sent. This PR fixes that by ensuring the response is sent as late as possible, whether or not it is a "single session" situation.
This commit is contained in:
parent
523d9c2def
commit
4476d0da6f
3 changed files with 30 additions and 6 deletions
|
|
@ -47,12 +47,16 @@ class DebugSession(Startable, Closeable):
|
|||
self._notify_disconnecting = notify_disconnecting
|
||||
|
||||
self._sock = sock
|
||||
self._pre_socket_close = None
|
||||
if ownsock:
|
||||
# Close the socket *after* calling sys.exit() (via notify_closing).
|
||||
def handle_closing(before):
|
||||
if before:
|
||||
return
|
||||
debug('closing session socket')
|
||||
proc = self._msgprocessor
|
||||
if self._pre_socket_close is not None:
|
||||
self._pre_socket_close()
|
||||
if proc is not None:
|
||||
try:
|
||||
proc.wait_while_connected(10) # seconds
|
||||
|
|
@ -134,8 +138,9 @@ class DebugSession(Startable, Closeable):
|
|||
|
||||
# internal methods for VSCodeMessageProcessor
|
||||
|
||||
def _handle_vsc_disconnect(self):
|
||||
def _handle_vsc_disconnect(self, pre_socket_close=None):
|
||||
debug('disconnecting')
|
||||
self._pre_socket_close = pre_socket_close # TODO: Fail if already set?
|
||||
self._notify_disconnecting(self)
|
||||
|
||||
def _handle_vsc_close(self):
|
||||
|
|
|
|||
|
|
@ -811,6 +811,7 @@ class VSCodeMessageProcessorBase(ipcjson.SocketIO, ipcjson.IpcChannel):
|
|||
self._notify_closing = notify_closing
|
||||
|
||||
self.server_thread = None
|
||||
self._closing = False
|
||||
self._closed = False
|
||||
self.readylock = threading.Lock()
|
||||
self.readylock.acquire() # Unlock at the end of start().
|
||||
|
|
@ -824,6 +825,10 @@ class VSCodeMessageProcessorBase(ipcjson.SocketIO, ipcjson.IpcChannel):
|
|||
with self._connlock:
|
||||
return _util.is_locked(self._connected)
|
||||
|
||||
@property
|
||||
def closed(self):
|
||||
return self._closed or self._closing
|
||||
|
||||
@property
|
||||
def listening(self):
|
||||
# TODO: must be disconnected?
|
||||
|
|
@ -882,9 +887,9 @@ class VSCodeMessageProcessorBase(ipcjson.SocketIO, ipcjson.IpcChannel):
|
|||
|
||||
def close(self):
|
||||
"""Stop the message processor and release its resources."""
|
||||
if self._closed:
|
||||
if self.closed:
|
||||
return
|
||||
self._closed = True
|
||||
self._closing = True
|
||||
debug('raw closing')
|
||||
|
||||
self._notify_closing()
|
||||
|
|
@ -895,6 +900,7 @@ class VSCodeMessageProcessorBase(ipcjson.SocketIO, ipcjson.IpcChannel):
|
|||
with self._connlock:
|
||||
_util.lock_release(self._listening)
|
||||
_util.lock_release(self._connected)
|
||||
self._closed = True
|
||||
|
||||
# VSC protocol handlers
|
||||
|
||||
|
|
@ -1080,8 +1086,20 @@ class VSCLifecycleMsgProcessor(VSCodeMessageProcessorBase):
|
|||
# TODO: docstring
|
||||
if self._debuggerstopped: # A "terminated" event must have been sent.
|
||||
self._wait_until_exiting(self.EXITWAIT)
|
||||
self._notify_disconnecting()
|
||||
self.send_response(request)
|
||||
|
||||
status = {'sent': False}
|
||||
|
||||
def disconnect_response():
|
||||
if status['sent']:
|
||||
return
|
||||
self.send_response(request)
|
||||
status['sent'] = True
|
||||
|
||||
self._notify_disconnecting(
|
||||
pre_socket_close=disconnect_response,
|
||||
)
|
||||
disconnect_response()
|
||||
|
||||
self._set_disconnected()
|
||||
|
||||
if self.start_reason == 'attach':
|
||||
|
|
@ -1089,7 +1107,7 @@ class VSCLifecycleMsgProcessor(VSCodeMessageProcessorBase):
|
|||
self._handle_detach()
|
||||
# TODO: We should be able drop the "launch" branch.
|
||||
elif self.start_reason == 'launch':
|
||||
if not self._closed:
|
||||
if not self.closed:
|
||||
# Closing the socket causes pydevd to resume all threads,
|
||||
# so just terminate the process altogether.
|
||||
sys.exit(0)
|
||||
|
|
|
|||
|
|
@ -512,6 +512,7 @@ class LifecycleTests(TestsBase, unittest.TestCase):
|
|||
done2, waitscript2 = lockfile2.wait_in_script(timeout=5)
|
||||
filename = self.write_script('spam.py', waitscript1 + waitscript2)
|
||||
addr = Address('localhost', 8888)
|
||||
#DebugAdapter.VERBOSE = True
|
||||
with DebugAdapter.start_for_attach(addr, filename) as adapter:
|
||||
with DebugClient() as editor:
|
||||
# Attach initially.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue