Better handling of crashed ycmd; restart command

Previously the YCM Vim client would go bonkers when ycmd crashed. Now the user
can continue using Vim just without YCM functionality.

Also added a :YcmRestartServer command to let the user restart ycmd if it
crashed. With a little luck, this will be rarely necessary.
This commit is contained in:
Strahinja Val Markovic 2013-10-15 15:27:54 -07:00
parent 436017bd4d
commit 18002e17df
3 changed files with 65 additions and 19 deletions

View File

@ -566,7 +566,11 @@ function! youcompleteme#Complete( findstart, base )
return -2 return -2
endif endif
return pyeval( 'ycm_state.CreateCompletionRequest().CompletionStartColumn()' ) py request = ycm_state.CreateCompletionRequest()
if !pyeval( 'bool(request)' )
return -2
endif
return pyeval( 'request.CompletionStartColumn()' )
else else
return s:CompletionsForQuery( a:base ) return s:CompletionsForQuery( a:base )
endif endif
@ -584,6 +588,13 @@ function! youcompleteme#OmniComplete( findstart, base )
endfunction endfunction
function! s:RestartServer()
py ycm_state.RestartServer()
endfunction
command! YcmRestartServer call s:RestartServer()
function! s:ShowDetailedDiagnostic() function! s:ShowDetailedDiagnostic()
py ycm_state.ShowDetailedDiagnostic() py ycm_state.ShowDetailedDiagnostic()
endfunction endfunction

View File

@ -198,6 +198,7 @@ def _GetCompleterForRequestData( request_data ):
@atexit.register @atexit.register
def _ServerShutdown(): def _ServerShutdown():
LOGGER.info( 'Server shutting down' )
if SERVER_STATE: if SERVER_STATE:
SERVER_STATE.Shutdown() SERVER_STATE.Shutdown()
extra_conf_store.Shutdown() extra_conf_store.Shutdown()

View File

@ -88,18 +88,30 @@ class YouCompleteMe( object ):
self._server_popen = subprocess.Popen( args, self._server_popen = subprocess.Popen( args,
stdout = fstdout, stdout = fstdout,
stderr = fstderr ) stderr = fstderr )
self._CheckIfServerCrashed() self._NotifyUserIfServerCrashed()
def _CheckIfServerCrashed( self ): def _IsServerAlive( self ):
server_crashed = self._server_popen.poll() returncode = self._server_popen.poll()
if server_crashed: # When the process hasn't finished yet, poll() returns None.
if self._server_stderr: return returncode is None
with open( self._server_stderr, 'r' ) as server_stderr_file:
vimsupport.PostMultiLineNotice( SERVER_CRASH_MESSAGE_STDERR_FILE +
server_stderr_file.read() ) def _NotifyUserIfServerCrashed( self ):
else: if self._IsServerAlive():
vimsupport.PostVimMessage( SERVER_CRASH_MESSAGE_SAME_STDERR ) return
if self._server_stderr:
with open( self._server_stderr, 'r' ) as server_stderr_file:
vimsupport.PostMultiLineNotice( SERVER_CRASH_MESSAGE_STDERR_FILE +
server_stderr_file.read() )
else:
vimsupport.PostVimMessage( SERVER_CRASH_MESSAGE_SAME_STDERR )
def RestartServer( self ):
vimsupport.PostVimMessage( 'Restarting ycmd server...' )
self.OnVimLeave()
self._SetupServer()
def CreateCompletionRequest( self, force_semantic = False ): def CreateCompletionRequest( self, force_semantic = False ):
@ -111,17 +123,23 @@ class YouCompleteMe( object ):
self._omnicomp.ShouldUseNow() ): self._omnicomp.ShouldUseNow() ):
self._latest_completion_request = OmniCompletionRequest( self._omnicomp ) self._latest_completion_request = OmniCompletionRequest( self._omnicomp )
else: else:
self._latest_completion_request = CompletionRequest( force_semantic ) self._latest_completion_request = ( CompletionRequest( force_semantic )
if self._IsServerAlive() else
None )
return self._latest_completion_request return self._latest_completion_request
def SendCommandRequest( self, arguments, completer ): def SendCommandRequest( self, arguments, completer ):
return SendCommandRequest( arguments, completer ) if self._IsServerAlive():
return SendCommandRequest( arguments, completer )
def GetDefinedSubcommands( self ): def GetDefinedSubcommands( self ):
return BaseRequest.PostDataToHandler( BuildRequestData(), if self._IsServerAlive():
'defined_subcommands' ) return BaseRequest.PostDataToHandler( BuildRequestData(),
'defined_subcommands' )
else:
return []
def GetCurrentCompletionRequest( self ): def GetCurrentCompletionRequest( self ):
@ -143,9 +161,11 @@ class YouCompleteMe( object ):
def OnFileReadyToParse( self ): def OnFileReadyToParse( self ):
self._CheckIfServerCrashed()
self._omnicomp.OnFileReadyToParse( None ) self._omnicomp.OnFileReadyToParse( None )
if not self._IsServerAlive():
self._NotifyUserIfServerCrashed()
extra_data = {} extra_data = {}
if self._user_options[ 'collect_identifiers_from_tags_files' ]: if self._user_options[ 'collect_identifiers_from_tags_files' ]:
extra_data[ 'tag_files' ] = _GetTagFiles() extra_data[ 'tag_files' ] = _GetTagFiles()
@ -159,26 +179,35 @@ class YouCompleteMe( object ):
def OnBufferUnload( self, deleted_buffer_file ): def OnBufferUnload( self, deleted_buffer_file ):
if not self._IsServerAlive():
return
SendEventNotificationAsync( 'BufferUnload', SendEventNotificationAsync( 'BufferUnload',
{ 'unloaded_buffer': deleted_buffer_file } ) { 'unloaded_buffer': deleted_buffer_file } )
def OnBufferVisit( self ): def OnBufferVisit( self ):
if not self._IsServerAlive():
return
extra_data = {} extra_data = {}
_AddUltiSnipsDataIfNeeded( extra_data ) _AddUltiSnipsDataIfNeeded( extra_data )
SendEventNotificationAsync( 'BufferVisit', extra_data ) SendEventNotificationAsync( 'BufferVisit', extra_data )
def OnInsertLeave( self ): def OnInsertLeave( self ):
if not self._IsServerAlive():
return
SendEventNotificationAsync( 'InsertLeave' ) SendEventNotificationAsync( 'InsertLeave' )
def OnVimLeave( self ): def OnVimLeave( self ):
self._server_popen.terminate() if self._IsServerAlive():
self._server_popen.terminate()
os.remove( self._temp_options_filename ) os.remove( self._temp_options_filename )
def OnCurrentIdentifierFinished( self ): def OnCurrentIdentifierFinished( self ):
if not self._IsServerAlive():
return
SendEventNotificationAsync( 'CurrentIdentifierFinished' ) SendEventNotificationAsync( 'CurrentIdentifierFinished' )
@ -200,6 +229,8 @@ class YouCompleteMe( object ):
def ShowDetailedDiagnostic( self ): def ShowDetailedDiagnostic( self ):
if not self._IsServerAlive():
return
debug_info = BaseRequest.PostDataToHandler( BuildRequestData(), debug_info = BaseRequest.PostDataToHandler( BuildRequestData(),
'detailed_diagnostic' ) 'detailed_diagnostic' )
if 'message' in debug_info: if 'message' in debug_info:
@ -207,8 +238,11 @@ class YouCompleteMe( object ):
def DebugInfo( self ): def DebugInfo( self ):
debug_info = BaseRequest.PostDataToHandler( BuildRequestData(), if self._IsServerAlive():
'debug_info' ) debug_info = BaseRequest.PostDataToHandler( BuildRequestData(),
'debug_info' )
else:
debug_info = 'Server crashed, no debug info from server'
debug_info += '\nServer running at: {0}'.format( debug_info += '\nServer running at: {0}'.format(
BaseRequest.server_location ) BaseRequest.server_location )
if self._server_stderr or self._server_stdout: if self._server_stderr or self._server_stdout: