Add timeout for requests.
This commit is contained in:
parent
361458534c
commit
af338669f3
4 changed files with 77 additions and 15 deletions
|
|
@ -15,13 +15,17 @@
|
|||
|
||||
import logging
|
||||
import json
|
||||
|
||||
from collections import namedtuple
|
||||
import vim
|
||||
|
||||
from vimspector import utils
|
||||
|
||||
PendingRequest = namedtuple( 'PendingRequest',
|
||||
[ 'msg', 'handler', 'failure_handler' ] )
|
||||
|
||||
class PendingRequest( object ):
|
||||
def __init__( self, msg, handler, failure_handler, expiry_id ):
|
||||
self.msg = msg
|
||||
self.handler = handler
|
||||
self.failure_handler = failure_handler
|
||||
self.expiry_id = expiry_id
|
||||
|
||||
|
||||
class DebugAdapterConnection( object ):
|
||||
|
|
@ -36,18 +40,40 @@ class DebugAdapterConnection( object ):
|
|||
self._next_message_id = 0
|
||||
self._outstanding_requests = {}
|
||||
|
||||
def DoRequest( self, handler, msg, failure_handler=None ):
|
||||
def DoRequest( self,
|
||||
handler,
|
||||
msg,
|
||||
failure_handler=None,
|
||||
timeout = 5000 ):
|
||||
this_id = self._next_message_id
|
||||
self._next_message_id += 1
|
||||
|
||||
msg[ 'seq' ] = this_id
|
||||
msg[ 'type' ] = 'request'
|
||||
|
||||
# TODO/FIXME: This is so messy
|
||||
expiry_id = vim.eval(
|
||||
'timer_start( {}, "vimspector#internal#channel#Timeout" )'.format(
|
||||
timeout ) )
|
||||
|
||||
self._outstanding_requests[ this_id ] = PendingRequest( msg,
|
||||
handler,
|
||||
failure_handler )
|
||||
failure_handler,
|
||||
expiry_id )
|
||||
self._SendMessage( msg )
|
||||
|
||||
def OnRequestTimeout( self, timer_id ):
|
||||
request_id = None
|
||||
for seq, request in self._outstanding_requests.items():
|
||||
if request.expiry_id == timer_id:
|
||||
self._AbortRequest( request, 'Timeout' )
|
||||
request_id = seq
|
||||
break
|
||||
|
||||
# Avoid modifying _outstanding_requests while looping
|
||||
if request_id is not None:
|
||||
del self._outstanding_requests[ request_id ]
|
||||
|
||||
def DoResponse( self, request, error, response ):
|
||||
this_id = self._next_message_id
|
||||
self._next_message_id += 1
|
||||
|
|
@ -69,6 +95,21 @@ class DebugAdapterConnection( object ):
|
|||
def Reset( self ):
|
||||
self._Write = None
|
||||
self._handler = None
|
||||
for _, request in self._outstanding_requests.items():
|
||||
self._AbortRequest( request, 'Closing down' )
|
||||
self._outstanding_requests.clear()
|
||||
|
||||
def _AbortRequest( self, request, reason ):
|
||||
self._logger.debug( 'Aborting request {} because {}'.format(
|
||||
json.dumps( request.msg ),
|
||||
reason ) )
|
||||
|
||||
_KillTimer( request )
|
||||
if request.failure_handler:
|
||||
request.failure_handler( reason, {} )
|
||||
else:
|
||||
utils.UserMessage( 'Request aborted: {}'.format( reason ) )
|
||||
|
||||
|
||||
def OnData( self, data ):
|
||||
data = bytes( data, 'utf-8' )
|
||||
|
|
@ -170,6 +211,8 @@ class DebugAdapterConnection( object ):
|
|||
self._logger.exception( 'Duplicate response: {}'.format( message ) )
|
||||
return
|
||||
|
||||
_KillTimer( request )
|
||||
|
||||
if message[ 'success' ]:
|
||||
if request.handler:
|
||||
request.handler( message )
|
||||
|
|
@ -181,7 +224,7 @@ class DebugAdapterConnection( object ):
|
|||
# TODO: Actually make this work
|
||||
reason = fmt
|
||||
else:
|
||||
message = 'No reason'
|
||||
reason = 'No reason'
|
||||
|
||||
self._logger.error( 'Request failed: {0}'.format( reason ) )
|
||||
if request.failure_handler:
|
||||
|
|
@ -203,3 +246,9 @@ class DebugAdapterConnection( object ):
|
|||
utils.UserMessage(
|
||||
'Unhandled request: {0}'.format( message[ 'command' ] ),
|
||||
persist = True )
|
||||
|
||||
|
||||
def _KillTimer( request ):
|
||||
if request.expiry_id is not None:
|
||||
vim.eval( 'timer_stop( {} )'.format( request.expiry_id ) )
|
||||
request.expiry_id = None
|
||||
|
|
|
|||
|
|
@ -189,6 +189,10 @@ class DebugSession( object ):
|
|||
if self._connection:
|
||||
self._connection.OnData( data )
|
||||
|
||||
def OnRequestTimeout( self, timer_id ):
|
||||
if self._connection:
|
||||
self._connection.OnRequestTimeout( timer_id )
|
||||
|
||||
def OnChannelClosed( self ):
|
||||
self._connection = None
|
||||
|
||||
|
|
@ -384,7 +388,7 @@ class DebugSession( object ):
|
|||
# scope)
|
||||
state = { 'done': False }
|
||||
|
||||
def handler( self ):
|
||||
def handler( *args ):
|
||||
state[ 'done' ] = True
|
||||
|
||||
self._connection.DoRequest( handler, {
|
||||
|
|
@ -392,11 +396,10 @@ class DebugSession( object ):
|
|||
'arguments': {
|
||||
'terminateDebugee': True
|
||||
},
|
||||
} )
|
||||
}, failure_handler = handler )
|
||||
|
||||
tries = 0
|
||||
while not state[ 'done' ] and tries < 10:
|
||||
tries = tries + 1
|
||||
# This request times out after 5 seconds
|
||||
while not state[ 'done' ]:
|
||||
vim.eval( 'vimspector#internal#{}#ForceRead()'.format(
|
||||
self._connection_type ) )
|
||||
|
||||
|
|
@ -404,7 +407,7 @@ class DebugSession( object ):
|
|||
self._connection_type ) )
|
||||
|
||||
def _StopDebugAdapter( self, callback = None ):
|
||||
def handler( message ):
|
||||
def handler( *args ):
|
||||
vim.eval( 'vimspector#internal#{}#StopDebugSession()'.format(
|
||||
self._connection_type ) )
|
||||
|
||||
|
|
@ -423,7 +426,7 @@ class DebugSession( object ):
|
|||
'arguments': {
|
||||
'terminateDebugee': True
|
||||
},
|
||||
} )
|
||||
}, failure_handler = handler )
|
||||
|
||||
def _SelectProcess( self, adapter_config, launch_config ):
|
||||
atttach_config = adapter_config[ 'attach' ]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue