Server now shuts down cleanly on VimClose

This commit is contained in:
Strahinja Val Markovic 2013-09-23 13:27:32 -07:00
parent 1730660555
commit f51a687297
4 changed files with 68 additions and 13 deletions

View File

@ -160,6 +160,12 @@ let g:ycm_auto_stop_csharp_server =
let g:ycm_csharp_server_port = let g:ycm_csharp_server_port =
\ get( g:, 'ycm_csharp_server_port', 2000 ) \ get( g:, 'ycm_csharp_server_port', 2000 )
let g:ycm_server_use_vim_stdout =
\ get( g:, 'ycm_server_use_vim_stdout', 0 )
let g:ycm_server_log_level =
\ get( g:, 'ycm_server_log_level', 'info' )
" On-demand loading. Let's use the autoload folder and not slow down vim's " On-demand loading. Let's use the autoload folder and not slow down vim's
" startup procedure. " startup procedure.
augroup youcompletemeStart augroup youcompletemeStart

View File

@ -19,6 +19,7 @@
import sys import sys
import os import os
import threading
# We want to have the YouCompleteMe/python directory on the Python PATH because # We want to have the YouCompleteMe/python directory on the Python PATH because
# all the code already assumes that it's there. This is a relic from before the # all the code already assumes that it's there. This is a relic from before the
@ -38,6 +39,7 @@ from bottle import run, request, response
import server_state import server_state
from ycm import extra_conf_store from ycm import extra_conf_store
from ycm import user_options_store from ycm import user_options_store
from ycm import utils
import argparse import argparse
# num bytes for the request body buffer; request.json only works if the request # num bytes for the request body buffer; request.json only works if the request
@ -66,10 +68,15 @@ def EventNotification():
getattr( SERVER_STATE.GetFiletypeCompleter( filetypes ), getattr( SERVER_STATE.GetFiletypeCompleter( filetypes ),
event_handler )( request_data ) event_handler )( request_data )
try:
if hasattr( extra_conf_store, event_handler ): if hasattr( extra_conf_store, event_handler ):
getattr( extra_conf_store, event_handler )( request_data ) getattr( extra_conf_store, event_handler )( request_data )
except OSError as e:
LOGGER.exception( e )
if event_name == 'VimLeave':
_ScheduleServerShutdown()
# TODO: shut down the server on VimClose
@app.post( '/run_completer_command' ) @app.post( '/run_completer_command' )
@ -140,6 +147,19 @@ def _JsonResponse( data ):
return json.dumps( data ) return json.dumps( data )
def _ScheduleServerShutdown():
# The reason why we want to schedule a shutdown in the near future instead of
# just shutting down right now is because we want the current request (the one
# that made us want to shutdown) to complete successfully first.
def Shutdown():
# sys.exit() doesn't work because we're not in the main thread.
utils.TerminateProcess( os.getpid() )
killer_thread = threading.Timer( 2, Shutdown )
killer_thread.start()
def Main(): def Main():
global LOGGER global LOGGER
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()

View File

@ -19,6 +19,8 @@
import tempfile import tempfile
import os import os
import sys
import signal
def IsIdentifierChar( char ): def IsIdentifierChar( char ):
return char.isalnum() or char == '_' return char.isalnum() or char == '_'
@ -36,3 +38,17 @@ def ToUtf8IfNeeded( string_or_unicode ):
def PathToTempDir(): def PathToTempDir():
return os.path.join( tempfile.gettempdir(), 'ycm_temp' ) return os.path.join( tempfile.gettempdir(), 'ycm_temp' )
# From here: http://stackoverflow.com/a/8536476/1672783
def TerminateProcess( pid ):
if sys.platform == 'win32':
import ctypes
PROCESS_TERMINATE = 1
handle = ctypes.windll.kernel32.OpenProcess( PROCESS_TERMINATE,
False,
pid )
ctypes.windll.kernel32.TerminateProcess( handle, -1 )
ctypes.windll.kernel32.CloseHandle( handle )
else:
os.kill( pid, signal.SIGTERM )

View File

@ -37,26 +37,39 @@ class YouCompleteMe( object ):
self._user_options = user_options self._user_options = user_options
self._omnicomp = OmniCompleter( user_options ) self._omnicomp = OmniCompleter( user_options )
self._current_completion_request = None self._current_completion_request = None
self._server_stdout = None
self._server_stderr = None
self._SetupServer()
def _SetupServer( self ):
server_port = SERVER_PORT_RANGE_START + os.getpid() server_port = SERVER_PORT_RANGE_START + os.getpid()
command = ''.join( [ 'python ', command = ''.join( [ 'python ',
_PathToServerScript(), _PathToServerScript(),
' --port=', ' --port=',
str( server_port ) ] ) str( server_port ),
' --log=',
self._user_options[ 'server_log_level' ] ] )
BaseRequest.server_location = 'http://localhost:' + str( server_port ) BaseRequest.server_location = 'http://localhost:' + str( server_port )
if self._user_options[ 'server_use_vim_stdout' ]:
subprocess.Popen( command, shell = True )
else:
filename_format = os.path.join( utils.PathToTempDir(), filename_format = os.path.join( utils.PathToTempDir(),
'server_{port}_{std}.log' ) 'server_{port}_{std}.log' )
self._server_stdout = filename_format.format( port=server_port, self._server_stdout = filename_format.format( port = server_port,
std='stdout' ) std = 'stdout' )
self._server_stderr = filename_format.format( port=server_port, self._server_stderr = filename_format.format( port = server_port,
std='stderr' ) std = 'stderr' )
with open( self._server_stderr, 'w' ) as fstderr: with open( self._server_stderr, 'w' ) as fstderr:
with open( self._server_stdout, 'w' ) as fstdout: with open( self._server_stdout, 'w' ) as fstdout:
subprocess.Popen( command, stdout=fstdout, stderr=fstderr, shell=True ) subprocess.Popen( command,
stdout = fstdout,
stderr = fstderr,
shell = True )
def CreateCompletionRequest( self ): def CreateCompletionRequest( self ):