def _SetupServer(self): server_port = utils.GetUnusedLocalhostPort() with tempfile.NamedTemporaryFile(delete=False) as options_file: self._temp_options_filename = options_file.name json.dump(dict(self._user_options), options_file) args = [ utils.PathToPythonInterpreter(), _PathToServerScript(), '--port={0}'.format(server_port), '--options_file={0}'.format(options_file.name), '--log={0}'.format(self._user_options['server_log_level']), '--idle_suicide_seconds={0}'.format( self._user_options['server_idle_suicide_seconds']) ] BaseRequest.server_location = 'http://localhost:' + str( server_port) if self._user_options['server_use_vim_stdout']: self._server_popen = subprocess.Popen(args) else: filename_format = os.path.join(utils.PathToTempDir(), 'server_{port}_{std}.log') self._server_stdout = filename_format.format(port=server_port, std='stdout') self._server_stderr = filename_format.format(port=server_port, std='stderr') # We need this on Windows otherwise bad things happen. See issue #637. stdin = subprocess.PIPE if utils.OnWindows() else None with open(self._server_stderr, 'w') as fstderr: with open(self._server_stdout, 'w') as fstdout: self._server_popen = subprocess.Popen(args, stdin=stdin, stdout=fstdout, stderr=fstderr) self._NotifyUserIfServerCrashed()
def _StartServer( self, request_data ): """ Start the OmniSharp server """ self._logger.info( 'startup' ) self._omnisharp_port = utils.GetUnusedLocalhostPort() solution_files, folder = _FindSolutionFiles( request_data[ 'filepath' ] ) if len( solution_files ) == 0: raise RuntimeError( 'Error starting OmniSharp server: no solutionfile found' ) elif len( solution_files ) == 1: solutionfile = solution_files[ 0 ] else: # multiple solutions found : if there is one whose name is the same # as the folder containing the file we edit, use this one # (e.g. if we have bla/Project.sln and we are editing # bla/Project/Folder/File.cs, use bla/Project.sln) filepath_components = _PathComponents( request_data[ 'filepath' ] ) solutionpath = _PathComponents( folder ) foldername = '' if len( filepath_components ) > len( solutionpath ): foldername = filepath_components[ len( solutionpath ) ] solution_file_candidates = [ solutionfile for solutionfile in solution_files if _GetFilenameWithoutExtension( solutionfile ) == foldername ] if len( solution_file_candidates ) == 1: solutionfile = solution_file_candidates[ 0 ] else: raise RuntimeError( 'Found multiple solution files instead of one!\n{0}'.format( solution_files ) ) omnisharp = os.path.join( os.path.abspath( os.path.dirname( __file__ ) ), 'OmniSharpServer/OmniSharp/bin/Debug/OmniSharp.exe' ) if not os.path.isfile( omnisharp ): raise RuntimeError( SERVER_NOT_FOUND_MSG.format( omnisharp ) ) path_to_solutionfile = os.path.join( folder, solutionfile ) # we need to pass the command to Popen as a string since we're passing # shell=True (as recommended by Python's doc) command = ( omnisharp + ' -p ' + str( self._omnisharp_port ) + ' -s ' + path_to_solutionfile ) if not utils.OnWindows(): command = 'mono ' + command filename_format = os.path.join( utils.PathToTempDir(), 'omnisharp_{port}_{sln}_{std}.log' ) self._filename_stdout = filename_format.format( port=self._omnisharp_port, sln=solutionfile, std='stdout' ) self._filename_stderr = filename_format.format( port=self._omnisharp_port, sln=solutionfile, std='stderr' ) with open( self._filename_stderr, 'w' ) as fstderr: with open( self._filename_stdout, 'w' ) as fstdout: # shell=True is needed for Windows so OmniSharp does not spawn # in a new visible window utils.SafePopen( command, stdout=fstdout, stderr=fstderr, shell=True ) self._logger.info( 'Starting OmniSharp server' )
def Main(): parser = argparse.ArgumentParser() parser.add_argument( '--host', type = str, default = 'localhost', help = 'server hostname') # Default of 0 will make the OS pick a free port for us parser.add_argument( '--port', type = int, default = 0, help = 'server port') parser.add_argument( '--log', type = str, default = 'info', help = 'log level, one of ' '[debug|info|warning|error|critical]' ) parser.add_argument( '--idle_suicide_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' ) parser.add_argument( '--stdout', type = str, default = None, help = 'optional file to use for stdout' ) parser.add_argument( '--stderr', type = str, default = None, help = 'optional file to use for stderr' ) parser.add_argument( '--keep_logfiles', action = 'store_true', default = None, help = 'retain logfiles after the server exits' ) args = parser.parse_args() if args.stdout is not None: sys.stdout = open(args.stdout, "w") if args.stderr is not None: sys.stderr = open(args.stderr, "w") numeric_level = getattr( logging, args.log.upper(), None ) if not isinstance( numeric_level, int ): raise ValueError( 'Invalid log level: %s' % args.log ) # Has to be called before any call to logging.getLogger() logging.basicConfig( format = '%(asctime)s - %(levelname)s - %(message)s', level = numeric_level ) options = ( json.load( open( args.options_file, 'r' ) ) if args.options_file else user_options_store.DefaultOptions() ) utils.RemoveIfExists( args.options_file ) options[ 'hmac_secret' ] = base64.b64decode( options[ 'hmac_secret' ] ) user_options_store.SetAll( options ) # This ensures that ycm_core is not loaded before extra conf # preload was run. YcmCoreSanityCheck() extra_conf_store.CallGlobalExtraConfYcmCorePreloadIfExists() # If not on windows, detach from controlling terminal to prevent # SIGINT from killing us. if not utils.OnWindows(): try: os.setsid() # setsid() can fail if the user started ycmd directly from a shell. except OSError: pass # 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. from ycm.server import handlers handlers.UpdateUserOptions( options ) SetUpSignalHandler(args.stdout, args.stderr, args.keep_logfiles) handlers.app.install( WatchdogPlugin( args.idle_suicide_seconds ) ) handlers.app.install( HmacPlugin( options[ 'hmac_secret' ] ) ) waitress.serve( handlers.app, host = args.host, port = args.port, threads = 30 )