New ycmd watchdog kills server when idle too long
Defaults are kill server after 12 hours of inactivity; the reason why it's 12 hours and not less is because we don't want to kill the server when the user just left his machine (and Vim) on during the night.
This commit is contained in:
parent
78107361b3
commit
262d8aad03
@ -29,6 +29,7 @@
|
||||
"server_use_vim_stdout": 0,
|
||||
"server_log_level": "info",
|
||||
"server_keep_logfiles": 0,
|
||||
"server_idle_shutdown_seconds": 43200,
|
||||
"auto_start_csharp_server": 1,
|
||||
"auto_stop_csharp_server": 1,
|
||||
"csharp_server_port": 2000
|
||||
|
78
python/ycm/server/watchdog_plugin.py
Normal file
78
python/ycm/server/watchdog_plugin.py
Normal file
@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2013 Strahinja Val Markovic <val@markovic.io>
|
||||
#
|
||||
# This file is part of YouCompleteMe.
|
||||
#
|
||||
# YouCompleteMe is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# YouCompleteMe is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import time
|
||||
import os
|
||||
import copy
|
||||
from ycm import utils
|
||||
from threading import Thread, Lock
|
||||
|
||||
# This class implements the Bottle plugin API:
|
||||
# http://bottlepy.org/docs/dev/plugindev.html
|
||||
#
|
||||
# The idea here is to decorate every route handler automatically so that on
|
||||
# every request, we log when the request was made. Then a watchdog thread checks
|
||||
# every check_interval_seconds whether the server has been idle for a time
|
||||
# greater that the passed-in idle_shutdown_seconds. If it has, we kill the
|
||||
# server.
|
||||
#
|
||||
# We want to do this so that if something goes bonkers in Vim and the server
|
||||
# never gets killed by the client, we don't end up with lots of zombie servers.
|
||||
class WatchdogPlugin( object ):
|
||||
name = 'watchdog'
|
||||
api = 2
|
||||
|
||||
|
||||
def __init__( self,
|
||||
idle_shutdown_seconds,
|
||||
check_interval_seconds = 60 * 10 ):
|
||||
self._check_interval_seconds = check_interval_seconds
|
||||
self._idle_shutdown_seconds = idle_shutdown_seconds
|
||||
self._last_request_time = time.time()
|
||||
self._last_request_time_lock = Lock()
|
||||
if idle_shutdown_seconds <= 0:
|
||||
return
|
||||
self._watchdog_thread = Thread( target = self._WatchdogMain )
|
||||
self._watchdog_thread.daemon = True
|
||||
self._watchdog_thread.start()
|
||||
|
||||
|
||||
def _GetLastRequestTime( self ):
|
||||
with self._last_request_time_lock:
|
||||
return copy.deepcopy( self._last_request_time )
|
||||
|
||||
|
||||
def _SetLastRequestTime( self, new_value ):
|
||||
with self._last_request_time_lock:
|
||||
self._last_request_time = new_value
|
||||
|
||||
|
||||
def _WatchdogMain( self ):
|
||||
while True:
|
||||
time.sleep( self._check_interval_seconds )
|
||||
if time.time() - self._GetLastRequestTime() > self._idle_shutdown_seconds:
|
||||
utils.TerminateProcess( os.getpid() )
|
||||
|
||||
|
||||
def __call__( self, callback ):
|
||||
def wrapper( *args, **kwargs ):
|
||||
self._SetLastRequestTime( time.time() )
|
||||
return callback( *args, **kwargs )
|
||||
return wrapper
|
||||
|
@ -28,6 +28,7 @@ import waitress
|
||||
import signal
|
||||
from ycm import user_options_store
|
||||
from ycm import extra_conf_store
|
||||
from ycm.server.watchdog_plugin import WatchdogPlugin
|
||||
|
||||
|
||||
def YcmCoreSanityCheck():
|
||||
@ -55,6 +56,8 @@ def Main():
|
||||
parser.add_argument( '--log', type = str, default = 'info',
|
||||
help = 'log level, one of '
|
||||
'[debug|info|warning|error|critical]' )
|
||||
parser.add_argument( '--idle_shutdown_seconds', type = int, default = 0,
|
||||
help = 'num idle seconds before server shuts down')
|
||||
parser.add_argument( '--options_file', type = str, default = '',
|
||||
help = 'file with user options, in JSON format' )
|
||||
args = parser.parse_args()
|
||||
@ -79,9 +82,10 @@ def Main():
|
||||
# This can't be a top-level import because it transitively imports
|
||||
# ycm_core which we want to be imported ONLY after extra conf
|
||||
# preload has executed.
|
||||
import handlers
|
||||
from ycm.server import handlers
|
||||
handlers.UpdateUserOptions( options )
|
||||
SetUpSignalHandler()
|
||||
handlers.app.install( WatchdogPlugin( args.idle_shutdown_seconds ) )
|
||||
waitress.serve( handlers.app,
|
||||
host = args.host,
|
||||
port = args.port,
|
||||
|
@ -41,9 +41,9 @@ try:
|
||||
except ImportError:
|
||||
USE_ULTISNIPS_DATA = False
|
||||
|
||||
SERVER_CRASH_MESSAGE_STDERR_FILE = 'The ycmd server crashed with output:\n'
|
||||
SERVER_CRASH_MESSAGE_STDERR_FILE = 'The ycmd server SHUT DOWN with output:\n'
|
||||
SERVER_CRASH_MESSAGE_SAME_STDERR = (
|
||||
'The ycmd server crashed, check console output for logs!' )
|
||||
'The ycmd server shut down, check console output for logs!' )
|
||||
|
||||
|
||||
class YouCompleteMe( object ):
|
||||
@ -69,7 +69,9 @@ class YouCompleteMe( object ):
|
||||
_PathToServerScript(),
|
||||
'--port={0}'.format( server_port ),
|
||||
'--options_file={0}'.format( options_file.name ),
|
||||
'--log={0}'.format( self._user_options[ 'server_log_level' ] ) ]
|
||||
'--log={0}'.format( self._user_options[ 'server_log_level' ] ),
|
||||
'--idle_shutdown_seconds={0}'.format(
|
||||
self._user_options[ 'server_idle_shutdown_seconds' ] ) ]
|
||||
|
||||
BaseRequest.server_location = 'http://localhost:' + str( server_port )
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user