diff --git a/python/ycm/completers/cs/cs_completer.py b/python/ycm/completers/cs/cs_completer.py index 9a5b6d48..0cce4ef3 100755 --- a/python/ycm/completers/cs/cs_completer.py +++ b/python/ycm/completers/cs/cs_completer.py @@ -19,7 +19,6 @@ # along with YouCompleteMe. If not, see . import os -from sys import platform import glob from ycm.completers.completer import Completer from ycm.server import responses @@ -28,7 +27,6 @@ import urllib2 import urllib import urlparse import json -import subprocess import logging SERVER_NOT_FOUND_MSG = ( 'OmniSharp server binary not found at {0}. ' + @@ -150,13 +148,14 @@ class CsharpCompleter( Completer ): if not os.path.isfile( omnisharp ): raise RuntimeError( SERVER_NOT_FOUND_MSG.format( omnisharp ) ) - if not platform.startswith( 'win' ): - omnisharp = 'mono ' + omnisharp - path_to_solutionfile = os.path.join( folder, solutionfile ) - # command has to be provided as one string for some reason - command = [ omnisharp + ' -p ' + str( self._omnisharp_port ) + ' -s ' + - path_to_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' ) @@ -168,7 +167,9 @@ class CsharpCompleter( Completer ): with open( self._filename_stderr, 'w' ) as fstderr: with open( self._filename_stdout, 'w' ) as fstdout: - subprocess.Popen( command, stdout=fstdout, stderr=fstderr, shell=True ) + # 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' ) diff --git a/python/ycm/utils.py b/python/ycm/utils.py index 92af12f5..5e7058ed 100644 --- a/python/ycm/utils.py +++ b/python/ycm/utils.py @@ -25,6 +25,7 @@ import functools import socket import stat from distutils.spawn import find_executable +import subprocess WIN_PYTHON27_PATH = 'C:\python27\pythonw.exe' WIN_PYTHON26_PATH = 'C:\python26\pythonw.exe' @@ -169,3 +170,18 @@ def AddThirdPartyFoldersToSysPath(): def ForceSemanticCompletion( request_data ): return ( 'force_semantic' in request_data and bool( request_data[ 'force_semantic' ] ) ) + +def SafePopen( args, bufsize = 0, executable = None, stdin = None, + stdout = None, stderr = None, preexec_fn = None, + close_fds = False, shell = False, cwd = None, env = None, + universal_newlines = False, startupinfo = None, + creationflags = 0 ): + if stdin is None: + # We need this on Windows otherwise bad things happen. See issue #637. + stdin = subprocess.PIPE if OnWindows() else None + + return subprocess.Popen( args, bufsize, executable, stdin, stdout, stderr, + preexec_fn, close_fds, shell, cwd, env, + universal_newlines, startupinfo, creationflags ) + + diff --git a/python/ycm/youcompleteme.py b/python/ycm/youcompleteme.py index e7d6caa7..028b9f94 100644 --- a/python/ycm/youcompleteme.py +++ b/python/ycm/youcompleteme.py @@ -19,7 +19,6 @@ import os import vim -import subprocess import tempfile import json from ycm import vimsupport @@ -94,7 +93,7 @@ class YouCompleteMe( object ): BaseRequest.server_location = 'http://localhost:' + str( server_port ) if self._user_options[ 'server_use_vim_stdout' ]: - self._server_popen = subprocess.Popen( args ) + self._server_popen = utils.SafePopen( args ) else: filename_format = os.path.join( utils.PathToTempDir(), 'server_{port}_{std}.log' ) @@ -103,15 +102,12 @@ class YouCompleteMe( object ): 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._server_popen = utils.SafePopen( args, + stdout = fstdout, + stderr = fstderr ) self._NotifyUserIfServerCrashed()