Ejemplo n.º 1
0
        public static BuildRequest Create(RequestLanguage language,
                                          string workingDirectory,
                                          IList<string> args,
                                          string keepAlive = null,
                                          string libDirectory = null)
        {
            Log("Creating BuildRequest");
            Log($"Working directory: {workingDirectory}");
            Log($"Lib directory: {libDirectory ?? "null"}");

            var requestLength = args.Count + 1 + (libDirectory == null ? 0 : 1);
            var requestArgs = ImmutableArray.CreateBuilder<Argument>(requestLength);

            requestArgs.Add(new Argument(ArgumentId.CurrentDirectory, 0, workingDirectory));

            if (keepAlive != null)
                requestArgs.Add(new Argument(ArgumentId.KeepAlive, 0, keepAlive));

            if (libDirectory != null)
                requestArgs.Add(new Argument(ArgumentId.LibEnvVariable, 0, libDirectory));

            for (int i = 0; i < args.Count; ++i)
            {
                var arg = args[i];
                Log($"argument[{i}] = {arg}");
                requestArgs.Add(new Argument(ArgumentId.CommandLineArgument, i, arg));
            }

            return new BuildRequest(BuildProtocolConstants.ProtocolVersion, language, requestArgs.ToImmutable());
        }
Ejemplo n.º 2
0
 public static Task<BuildResponse> RunServerCompilation(
     RequestLanguage language,
     List<string> arguments,
     BuildPaths buildPaths,
     string keepAlive,
     string libEnvVariable,
     CancellationToken cancellationToken) => Task.FromResult<BuildResponse>(null);
Ejemplo n.º 3
0
 public TestableDesktopBuildClient(
     RequestLanguage langauge,
     CompileFunc compileFunc,
     string pipeName,
     Func<string, bool> createServerFunc) : base(langauge, compileFunc, new Mock<IAnalyzerAssemblyLoader>().Object)
 {
     _pipeName = pipeName;
     _createServerFunc = createServerFunc;
 }
Ejemplo n.º 4
0
 private TestableDesktopBuildClient CreateClient(
     RequestLanguage? language = null,
     CompileFunc compileFunc = null,
     Func<string, bool> createServerFunc = null)
 {
     language = language ?? RequestLanguage.CSharpCompile;
     compileFunc = compileFunc ?? delegate { return 0; };
     createServerFunc = createServerFunc ?? TryCreateServer;
     return new TestableDesktopBuildClient(language.Value, compileFunc, _pipeName, createServerFunc);
 }
Ejemplo n.º 5
0
 internal static int Run(IEnumerable<string> arguments, IEnumerable<string> extraArguments, RequestLanguage language, CompileFunc compileFunc, IAnalyzerAssemblyLoader analyzerAssemblyLoader)
 {
     var client = new DesktopBuildClient(language, compileFunc, analyzerAssemblyLoader);
     var clientDir = AppDomain.CurrentDomain.BaseDirectory;
     var sdkDir = RuntimeEnvironment.GetRuntimeDirectory();
     var workingDir = Directory.GetCurrentDirectory();
     var buildPaths = new BuildPaths(clientDir: clientDir, workingDir: workingDir, sdkDir: sdkDir);
     var originalArguments = BuildClient.GetCommandLineArgs(arguments).Concat(extraArguments).ToArray();
     return client.RunCompilation(originalArguments, buildPaths).ExitCode;
 }
Ejemplo n.º 6
0
 public static Task<BuildResponse> RunServerCompilation(
     RequestLanguage language,
     List<string> arguments,
     BuildPaths buildPaths,
     string keepAlive,
     string libEnvVariable,
     CancellationToken cancellationToken)
 {
     throw new NotSupportedException();
 }
Ejemplo n.º 7
0
 internal static int Run(IEnumerable<string> arguments, RequestLanguage language, CompileFunc compileFunc)
 {
     // BTODO: Should be using BuildClient.GetCommandLineArgs(arguments) here.  But the native invoke 
     // ends up giving us both CoreRun and the exe file.  Need to find a good way to remove the host 
     // as well as the EXE argument. 
     var client = new CoreClrBuildClient(language, compileFunc);
     var clientDir = AppContext.BaseDirectory;
     var workingDir = Directory.GetCurrentDirectory();
     var buildPaths = new BuildPaths(clientDir: clientDir, workingDir: workingDir, sdkDir: null);
     return client.RunCompilation(arguments, buildPaths);
 }
Ejemplo n.º 8
0
 internal static int Run(IEnumerable<string> arguments, RequestLanguage language, CompileFunc compileFunc)
 {
     // Should be using BuildClient.GetCommandLineArgs(arguments) here.  But the native invoke
     // ends up giving us both CoreRun and the exe file.  Need to find a good way to remove the host
     // as well as the EXE argument.
     // https://github.com/dotnet/roslyn/issues/6677
     var client = new CoreClrBuildClient(language, compileFunc);
     var clientDir = AppContext.BaseDirectory;
     var workingDir = Directory.GetCurrentDirectory();
     var tempDir = Path.GetTempPath();
     var buildPaths = new BuildPaths(clientDir: clientDir, workingDir: workingDir, sdkDir: null, tempDir: tempDir);
     return client.RunCompilation(arguments, buildPaths).ExitCode;
 }
Ejemplo n.º 9
0
 public static Task<BuildResponse> RunServerCompilation(
     RequestLanguage language,
     List<string> arguments,
     BuildPaths buildPaths,
     string keepAlive,
     string libEnvVariable,
     CancellationToken cancellationToken)
     => DesktopBuildClient.RunServerCompilation(
         language,
         arguments,
         buildPaths,
         keepAlive,
         libEnvVariable,
         cancellationToken);
Ejemplo n.º 10
0
        public BuildRequest(uint protocolVersion,
                            RequestLanguage language,
                            ImmutableArray<Argument> arguments)
        {
            ProtocolVersion = protocolVersion;
            Language = language;

            if (arguments.Length > ushort.MaxValue)
            {
                throw new ArgumentOutOfRangeException(nameof(arguments),
                    "Too many arguments: maximum of "
                    + ushort.MaxValue + " arguments allowed.");
            }
            Arguments = arguments;
        }
Ejemplo n.º 11
0
        public BuildRequest(uint protocolVersion,
                            RequestLanguage language,
                            IEnumerable<Argument> arguments)
        {
            ProtocolVersion = protocolVersion;
            Language = language;
            Arguments = new ReadOnlyCollection<Argument>(arguments.ToList());

            if (Arguments.Count > ushort.MaxValue)
            {
                throw new ArgumentOutOfRangeException(nameof(arguments),
                    "Too many arguments: maximum of "
                    + ushort.MaxValue + " arguments allowed.");
            }
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Run a compilation through the compiler server and print the output
        /// to the console. If the compiler server fails, run the fallback
        /// compiler.
        /// </summary>
        public static int RunWithConsoleOutput(
            string[] args,
            string clientDir,
            string workingDir,
            string sdkDir,
            IAnalyzerAssemblyLoader analyzerLoader,
            RequestLanguage language,
            Func<string, string, string[], IAnalyzerAssemblyLoader, int> fallbackCompiler)
        {
            args = args.Select(arg => arg.Trim()).ToArray();

            bool hasShared;
            string keepAlive;
            string errorMessage;
            List<string> parsedArgs;
            if (!CommandLineParser.TryParseClientArgs(
                    args,
                    out parsedArgs,
                    out hasShared,
                    out keepAlive,
                    out errorMessage))
            {
                Console.Out.WriteLine(errorMessage);
                return CommonCompiler.Failed;
            }

            if (hasShared)
            {
                var responseTask = TryRunServerCompilation(
                    language,
                    clientDir,
                    workingDir,
                    parsedArgs,
                    default(CancellationToken),
                    keepAlive: keepAlive,
                    libEnvVariable: Environment.GetEnvironmentVariable("LIB"));

                var response = responseTask.Result;
                if (response != null)
                {
                    return HandleResponse(response, clientDir, sdkDir, analyzerLoader, fallbackCompiler, parsedArgs);
                }
            }

            return fallbackCompiler(clientDir, sdkDir, parsedArgs.ToArray(), analyzerLoader);
        }
Ejemplo n.º 13
0
 public static Task<BuildResponse> RunServerCompilation(
     RequestLanguage language,
     List<string> arguments,
     BuildPaths buildPaths,
     string keepAlive,
     string libEnvVariable,
     CancellationToken cancellationToken)
 {
     return RunServerCompilationCore(
         language,
         arguments,
         buildPaths,
         GetPipeNameFromFileInfo(buildPaths.ClientDirectory),
         keepAlive,
         libEnvVariable,
         TryCreateServerCore,
         cancellationToken);
 }
Ejemplo n.º 14
0
 public static Task<BuildResponse> RunServerCompilation(
     RequestLanguage language,
     List<string> arguments,
     BuildPaths buildPaths,
     string keepAlive,
     string libEnvVariable,
     CancellationToken cancellationToken)
 {
     return RunServerCompilationCore(
         language,
         arguments,
         buildPaths,
         GetPipeNameForPath(buildPaths.ClientDirectory),
         keepAlive,
         libEnvVariable,
         timeoutOverride: null,
         tryCreateServerFunc: TryCreateServerCore,
         cancellationToken: cancellationToken);
 }
Ejemplo n.º 15
0
 internal DesktopBuildClient(RequestLanguage language, CompileFunc compileFunc, IAnalyzerAssemblyLoader analyzerAssemblyLoader)
 {
     _language = language;
     _compileFunc = compileFunc;
     _analyzerAssemblyLoader = analyzerAssemblyLoader;
 }
Ejemplo n.º 16
0
        private static Task<BuildResponse> RunServerCompilationCore(
            RequestLanguage language,
            List<string> arguments,
            BuildPaths buildPaths,
            string pipeName,
            string keepAlive,
            string libEnvVariable,
            Func<string, string, bool> tryCreateServerFunc,
            CancellationToken cancellationToken)
        {

            var clientDir = buildPaths.ClientDirectory;

            var clientMutexName = $"{pipeName}.client";
            bool holdsMutex;
            using (var clientMutex = new Mutex(initiallyOwned: true,
                                               name: clientMutexName,
                                               createdNew: out holdsMutex))
            {
                try
                {
                    if (!holdsMutex)
                    {
                        try
                        {
                            holdsMutex = clientMutex.WaitOne(TimeOutMsNewProcess);

                            if (!holdsMutex)
                            {
                                return Task.FromResult<BuildResponse>(null);
                            }
                        }
                        catch (AbandonedMutexException)
                        {
                            holdsMutex = true;
                        }
                    }

                    // Check for an already running server
                    var serverMutexName = $"{pipeName}.server";
                    Mutex mutexIgnore;
                    bool wasServerRunning = Mutex.TryOpenExisting(serverMutexName, out mutexIgnore);
                    var timeout = wasServerRunning ? TimeOutMsExistingProcess : TimeOutMsNewProcess;

                    NamedPipeClientStream pipe = null;

                    if (wasServerRunning || tryCreateServerFunc(clientDir, pipeName))
                    {
                        pipe = TryConnectToServer(pipeName,
                                                   timeout,
                                                   cancellationToken);
                    }

                    if (pipe != null)
                    {
                        var request = BuildRequest.Create(language,
                                                          buildPaths.WorkingDirectory,
                                                          arguments,
                                                          keepAlive,
                                                          libEnvVariable);

                        return TryCompile(pipe, request, cancellationToken);
                    }
                }
                finally
                {
                    if (holdsMutex)
                    {
                        clientMutex.ReleaseMutex();
                    }
                }
            }

            return null;
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Returns a Task with a null BuildResponse if no server
        /// response was received.
        /// </summary>
        public static Task <BuildResponse> TryRunServerCompilation(
            RequestLanguage language,
            string workingDir,
            IList <string> arguments,
            CancellationToken cancellationToken,
            string libEnvVariable = null)
        {
            try
            {
                NamedPipeClientStream pipe;

                var  expectedServerExePath = Path.Combine(GetExpectedServerExeDir(), s_serverName);
                var  mutexName             = expectedServerExePath.Replace('\\', '/');
                bool holdsMutex;
                using (var mutex = new Mutex(initiallyOwned: true,
                                             name: mutexName,
                                             createdNew: out holdsMutex))
                {
                    try
                    {
                        if (!holdsMutex)
                        {
                            try
                            {
                                holdsMutex = mutex.WaitOne(TimeOutMsNewProcess,
                                                           exitContext: false);
                            }
                            catch (AbandonedMutexException)
                            {
                                holdsMutex = true;
                            }
                        }

                        if (holdsMutex)
                        {
                            var request = BuildRequest.Create(language, workingDir, arguments, libEnvVariable);
                            // Check for already running processes in case someone came in before us
                            pipe = TryExistingProcesses(expectedServerExePath, cancellationToken);
                            if (pipe != null)
                            {
                                return(TryCompile(pipe, request, cancellationToken));
                            }
                            else
                            {
                                int processId = TryCreateServerProcess(expectedServerExePath);
                                if (processId != 0 &&
                                    null != (pipe = TryConnectToProcess(processId,
                                                                        TimeOutMsNewProcess,
                                                                        cancellationToken)))
                                {
                                    // Let everyone else access our process
                                    mutex.ReleaseMutex();
                                    holdsMutex = false;

                                    return(TryCompile(pipe, request, cancellationToken));
                                }
                            }
                        }
                    }
                    finally
                    {
                        if (holdsMutex)
                        {
                            mutex.ReleaseMutex();
                        }
                    }
                }
            }
            // Swallow all unhandled exceptions from server compilation. If
            // they are show-stoppers then they will crash the in-proc
            // compilation as well
            // TODO: Put in non-fatal Watson code so we still get info
            // when things unexpectedely fail
            catch { }
            return(Task.FromResult <BuildResponse>(null));
        }
Ejemplo n.º 18
0
        internal static CompileFunc GetCompileFunc(RequestLanguage language)
        {
            Func<string[], string, string, string, TextWriter, IAnalyzerAssemblyLoader, int> func;
            switch (language)
            {
                case RequestLanguage.CSharpCompile:
                    func = csc.Microsoft.CodeAnalysis.CSharp.CommandLine.Program.Run;
                    break;
                case RequestLanguage.VisualBasicCompile:
                    func = vbc.Microsoft.CodeAnalysis.VisualBasic.CommandLine.Program.Run;
                    break;
                default:
                    throw new InvalidOperationException();
            }

            return (args, buildPaths, textWriter, loader) => func(args, buildPaths.ClientDirectory, buildPaths.WorkingDirectory, buildPaths.SdkDirectory, textWriter, loader);
        }
Ejemplo n.º 19
0
 internal static DesktopBuildClient CreateBuildClient(
     RequestLanguage language,
     CompileFunc compileFunc = null,
     TextWriter textWriter = null,
     IAnalyzerAssemblyLoader analyzerAssemblyLoader = null)
 {
     compileFunc = compileFunc ?? GetCompileFunc(language);
     textWriter = textWriter ?? new StringWriter();
     analyzerAssemblyLoader = analyzerAssemblyLoader ?? new Mock<IAnalyzerAssemblyLoader>(MockBehavior.Strict).Object;
     return new DesktopBuildClient(language, compileFunc, analyzerAssemblyLoader);
 }
Ejemplo n.º 20
0
        /// <summary>
        /// Returns a Task with a null BuildResponse if no server
        /// response was received.
        /// </summary>
        public static Task<BuildResponse> TryRunServerCompilation(
            RequestLanguage language,
            string clientDir,
            string workingDir,
            IList<string> arguments,
            CancellationToken cancellationToken,
            string keepAlive = null,
            string libEnvVariable = null)
        {
            try
            {
                if (clientDir == null)
                    return Task.FromResult<BuildResponse>(null);

                var pipeName = GetBasePipeName(clientDir);

                var clientMutexName = $"{pipeName}.client";
                bool holdsMutex;
                using (var clientMutex = new Mutex(initiallyOwned: true,
                                                   name: clientMutexName,
                                                   createdNew: out holdsMutex))
                {
                    try
                    {
                        if (!holdsMutex)
                        {
                            try
                            {
                                holdsMutex = clientMutex.WaitOne(TimeOutMsNewProcess);

                                if (!holdsMutex)
                                    return Task.FromResult<BuildResponse>(null);
                            }
                            catch (AbandonedMutexException)
                            {
                                holdsMutex = true;
                            }
                        }

                        // Check for an already running server
                        var serverMutexName = $"{pipeName}.server";
                        Mutex mutexIgnore;
                        bool wasServerRunning = Mutex.TryOpenExisting(serverMutexName, out mutexIgnore);
                        var timeout = wasServerRunning ? TimeOutMsExistingProcess : TimeOutMsNewProcess;

                        NamedPipeClientStream pipe = null;

                        if (wasServerRunning || TryCreateServerProcess(clientDir, pipeName))
                        {
                            pipe = TryConnectToProcess(pipeName,
                                                       timeout,
                                                       cancellationToken);
                        }

                        if (pipe != null)
                        {
                            var request = BuildRequest.Create(language,
                                                              workingDir,
                                                              arguments,
                                                              keepAlive,
                                                              libEnvVariable);

                            return TryCompile(pipe, request, cancellationToken);
                        }
                    }
                    finally
                    {
                        if (holdsMutex)
                            clientMutex.ReleaseMutex();
                    }
                }
            }
            // Swallow all unhandled exceptions from server compilation. If
            // they are show-stoppers then they will crash the in-proc
            // compilation as well
            // TODO: Put in non-fatal Watson code so we still get info
            // when things unexpectedly fail
            catch { }
            return Task.FromResult<BuildResponse>(null);
        }
Ejemplo n.º 21
0
 internal BuildClient(RequestLanguage language, CompileFunc compileFunc, CompileOnServerFunc compileOnServerFunc)
 {
     _language            = language;
     _compileFunc         = compileFunc;
     _compileOnServerFunc = compileOnServerFunc;
 }
Ejemplo n.º 22
0
        private async Task RunCompilationAsync(RequestLanguage language, string pipeName, int i)
        {
            var compilationDir = Temp.CreateDirectory();

            TempFile sourceFile;
            string exeFileName;
            string prefix;
            string sourceText;

            if (language == RequestLanguage.CSharpCompile)
            {
                exeFileName = $"hellocs{i}.exe";
                prefix = "CS";
                sourceFile = compilationDir.CreateFile($"hello{i}.cs");
                sourceText =
$@"using System;
class Hello 
{{
    public static void Main()
    {{ Console.WriteLine(""CS Hello number {i}""); }}
}}";
            }
            else
            {
                exeFileName = $"hellovb{i}.exe";
                prefix = "VB";
                sourceFile = compilationDir.CreateFile($"hello{i}.vb");
                sourceText =
$@"Imports System
Module Hello 
    Sub Main()
       Console.WriteLine(""VB Hello number {i}"") 
    End Sub
End Module";
            }

            await sourceFile.WriteAllTextAsync(sourceText);

            // Create a client to run the build.  Infinite timeout is used to account for the 
            // case where these tests are run under extreme load.  In high load scenarios the 
            // client will correctly drop down to a local compilation if the server doesn't respond
            // fast enough.
            var client = ServerUtil.CreateBuildClient(language);
            client.TimeoutOverride = Timeout.Infinite;

            // Compile the code.  Use
            var buildPaths = new BuildPaths(
                clientDir: CompilerDirectory,
                workingDir: compilationDir.Path,
                sdkDir: RuntimeEnvironment.GetRuntimeDirectory());
            var result = await client.RunCompilationAsync(new[] { $"/shared:{pipeName}", "/nologo", Path.GetFileName(sourceFile.Path), $"/out:{exeFileName}" }, buildPaths);
            Assert.Equal(0, result.ExitCode);
            Assert.True(result.RanOnServer);

            // Run the EXE and verify it prints the desired output.
            var exeFile = Temp.AddFile(GetResultFile(compilationDir, exeFileName));
            var exeResult = RunCompilerOutput(exeFile);
            Assert.Equal($"{prefix} Hello number {i}\r\n", exeResult.Output);
        }
Ejemplo n.º 23
0
 private TestableDesktopBuildClient CreateClient(RequestLanguage? language = null, CompileFunc compileFunc = null)
 {
     language = language ?? RequestLanguage.CSharpCompile;
     compileFunc = compileFunc ?? delegate { return 0; };
     return new TestableDesktopBuildClient(language.Value, compileFunc, _pipeName, _serverInfo.TryCreateServer);
 }
Ejemplo n.º 24
0
        public static Task<BuildResponse> RunServerCompilation(
            RequestLanguage language,
            List<string> arguments,
            BuildPaths buildPaths,
            string keepAlive,
            string libEnvVariable,
            CancellationToken cancellationToken)
        {
            var pipeNameOpt = GetPipeNameForPathOpt(buildPaths.ClientDirectory);

            if (pipeNameOpt == null)
            {
                return Task.FromResult<BuildResponse>(new RejectedBuildResponse());
            }

            return RunServerCompilationCore(
                language,
                arguments,
                buildPaths,
                pipeNameOpt,
                keepAlive,
                libEnvVariable,
                timeoutOverride: null,
                tryCreateServerFunc: TryCreateServerCore,
                cancellationToken: cancellationToken);
        }
Ejemplo n.º 25
0
        internal static Task<BuildResponse> RunServerCompilationCore(
            RequestLanguage language,
            List<string> arguments,
            BuildPathsAlt buildPaths,
            string pipeName,
            string keepAlive,
            string libEnvVariable,
            int? timeoutOverride,
            Func<string, string, bool> tryCreateServerFunc,
            CancellationToken cancellationToken)
        {
            if (pipeName == null)
            {
                return Task.FromResult<BuildResponse>(new RejectedBuildResponse());
            }

            if (buildPaths.TempDirectory == null)
            {
                return Task.FromResult<BuildResponse>(new RejectedBuildResponse());
            }

            var clientDir = buildPaths.ClientDirectory;
            var timeoutNewProcess = timeoutOverride ?? TimeOutMsNewProcess;
            var timeoutExistingProcess = timeoutOverride ?? TimeOutMsExistingProcess;
            var clientMutexName = GetClientMutexName(pipeName);
            bool holdsMutex;
            using (var clientMutex = new Mutex(initiallyOwned: true,
                                               name: clientMutexName,
                                               createdNew: out holdsMutex))
            {
                try
                {
                    if (!holdsMutex)
                    {
                        try
                        {
                            holdsMutex = clientMutex.WaitOne(timeoutNewProcess);

                            if (!holdsMutex)
                            {
                                return Task.FromResult<BuildResponse>(new RejectedBuildResponse());
                            }
                        }
                        catch (AbandonedMutexException)
                        {
                            holdsMutex = true;
                        }
                    }

                    // Check for an already running server
                    var serverMutexName = GetServerMutexName(pipeName);
                    bool wasServerRunning = WasServerMutexOpen(serverMutexName);
                    var timeout = wasServerRunning ? timeoutExistingProcess : timeoutNewProcess;

                    NamedPipeClientStream pipe = null;

                    if (wasServerRunning || tryCreateServerFunc(clientDir, pipeName))
                    {
                        pipe = TryConnectToServer(pipeName,
                                                  timeout,
                                                  cancellationToken);
                    }

                    if (pipe != null)
                    {
                        var request = BuildRequest.Create(language,
                                                          buildPaths.WorkingDirectory,
                                                          buildPaths.TempDirectory,
                                                          arguments,
                                                          keepAlive,
                                                          libEnvVariable);

                        return TryCompile(pipe, request, cancellationToken);
                    }
                }
                finally
                {
                    if (holdsMutex)
                    {
                        clientMutex.ReleaseMutex();
                    }
                }
            }

            return Task.FromResult<BuildResponse>(new RejectedBuildResponse());
        }
Ejemplo n.º 26
0
        private static Task<BuildResponse> RunServerCompilationCore(
            RequestLanguage language,
            List<string> arguments,
            BuildPaths buildPaths,
            string pipeName,
            string keepAlive,
            string libEnvVariable,
            int? timeoutOverride,
            Func<string, string, bool> tryCreateServerFunc,
            CancellationToken cancellationToken)
        {
            var alt = new BuildPathsAlt(
                buildPaths.ClientDirectory,
                buildPaths.WorkingDirectory,
                buildPaths.SdkDirectory,
                buildPaths.TempDirectory);

            return BuildServerConnection.RunServerCompilationCore(
                language,
                arguments,
                alt,
                pipeName,
                keepAlive,
                libEnvVariable,
                timeoutOverride,
                tryCreateServerFunc,
                cancellationToken);
        }
Ejemplo n.º 27
0
 private CoreClrBuildClient(RequestLanguage language, CompileFunc compileFunc)
 {
     _language    = language;
     _compileFunc = compileFunc;
 }
Ejemplo n.º 28
0
 internal DesktopBuildClient(RequestLanguage language, CompileFunc compileFunc, IAnalyzerAssemblyLoader analyzerAssemblyLoader)
 {
     _language               = language;
     _compileFunc            = compileFunc;
     _analyzerAssemblyLoader = analyzerAssemblyLoader;
 }
Ejemplo n.º 29
0
        /// <summary>
        /// Returns a Task with a null BuildResponse if no server
        /// response was received.
        /// </summary>
        public static Task <BuildResponse> TryRunServerCompilation(
            RequestLanguage language,
            string clientDir,
            string workingDir,
            IList <string> arguments,
            CancellationToken cancellationToken,
            string keepAlive      = null,
            string libEnvVariable = null)
        {
            try
            {
                NamedPipeClientStream pipe;

                if (clientDir == null)
                {
                    return(Task.FromResult <BuildResponse>(null));
                }

                var  pipeName = GetPipeName(clientDir);
                bool holdsMutex;
                using (var mutex = new Mutex(initiallyOwned: true,
                                             name: pipeName,
                                             createdNew: out holdsMutex))
                {
                    try
                    {
                        if (!holdsMutex)
                        {
                            try
                            {
                                holdsMutex = mutex.WaitOne(TimeOutMsNewProcess);
                            }
                            catch (AbandonedMutexException)
                            {
                                holdsMutex = true;
                            }
                        }

                        if (holdsMutex)
                        {
                            var request = BuildRequest.Create(language, workingDir, arguments, keepAlive, libEnvVariable);
                            // Check for already running processes in case someone came in before us
                            string availablePipeName;
                            if (null != (pipe = TryAllProcesses(pipeName,
                                                                TimeOutMsExistingProcess,
                                                                cancellationToken,
                                                                out availablePipeName)))
                            {
                                return(TryCompile(pipe, request, cancellationToken));
                            }
                            else
                            {
                                if (TryCreateServerProcess(clientDir, availablePipeName) &&
                                    null != (pipe = TryConnectToProcess(availablePipeName,
                                                                        TimeOutMsNewProcess,
                                                                        cancellationToken)))
                                {
                                    // Let everyone else access our process
                                    mutex.ReleaseMutex();
                                    holdsMutex = false;

                                    return(TryCompile(pipe, request, cancellationToken));
                                }
                            }
                        }
                    }
                    finally
                    {
                        if (holdsMutex)
                        {
                            mutex.ReleaseMutex();
                        }
                    }
                }
            }
            // Swallow all unhandled exceptions from server compilation. If
            // they are show-stoppers then they will crash the in-proc
            // compilation as well
            // TODO: Put in non-fatal Watson code so we still get info
            // when things unexpectedly fail
            catch { }
            return(Task.FromResult <BuildResponse>(null));
        }
Ejemplo n.º 30
0
        private static Task <BuildResponse> RunServerCompilationCore(
            RequestLanguage language,
            List <string> arguments,
            BuildPaths buildPaths,
            string pipeName,
            string keepAlive,
            string libEnvVariable,
            Func <string, string, bool> tryCreateServerFunc,
            CancellationToken cancellationToken)
        {
            var clientDir = buildPaths.ClientDirectory;

            var  clientMutexName = BuildProtocolConstants.GetClientMutexName(pipeName);
            bool holdsMutex;

            using (var clientMutex = new Mutex(initiallyOwned: true,
                                               name: clientMutexName,
                                               createdNew: out holdsMutex))
            {
                try
                {
                    if (!holdsMutex)
                    {
                        try
                        {
                            holdsMutex = clientMutex.WaitOne(TimeOutMsNewProcess);

                            if (!holdsMutex)
                            {
                                return(Task.FromResult <BuildResponse>(null));
                            }
                        }
                        catch (AbandonedMutexException)
                        {
                            holdsMutex = true;
                        }
                    }

                    // Check for an already running server
                    var   serverMutexName = BuildProtocolConstants.GetServerMutexName(pipeName);
                    Mutex mutexIgnore;
                    bool  wasServerRunning = Mutex.TryOpenExisting(serverMutexName, out mutexIgnore);
                    var   timeout          = wasServerRunning ? TimeOutMsExistingProcess : TimeOutMsNewProcess;

                    NamedPipeClientStream pipe = null;

                    if (wasServerRunning || tryCreateServerFunc(clientDir, pipeName))
                    {
                        pipe = TryConnectToServer(pipeName,
                                                  timeout,
                                                  cancellationToken);
                    }

                    if (pipe != null)
                    {
                        var request = BuildRequest.Create(language,
                                                          buildPaths.WorkingDirectory,
                                                          arguments,
                                                          keepAlive,
                                                          libEnvVariable);

                        return(TryCompile(pipe, request, cancellationToken));
                    }
                }
                finally
                {
                    if (holdsMutex)
                    {
                        clientMutex.ReleaseMutex();
                    }
                }
            }

            return(Task.FromResult <BuildResponse>(null));
        }
Ejemplo n.º 31
0
        /// <summary>
        /// Returns a Task with a null BuildResponse if no server
        /// response was received.
        /// </summary>
        public static Task <BuildResponse> TryRunServerCompilation(
            RequestLanguage language,
            string clientDir,
            string workingDir,
            IList <string> arguments,
            CancellationToken cancellationToken,
            string keepAlive      = null,
            string libEnvVariable = null)
        {
            try
            {
                if (clientDir == null)
                {
                    return(Task.FromResult <BuildResponse>(null));
                }

                var pipeName = GetBasePipeName(clientDir);

                var  clientMutexName = $"{pipeName}.client";
                bool holdsMutex;
                using (var clientMutex = new Mutex(initiallyOwned: true,
                                                   name: clientMutexName,
                                                   createdNew: out holdsMutex))
                {
                    try
                    {
                        if (!holdsMutex)
                        {
                            try
                            {
                                holdsMutex = clientMutex.WaitOne(TimeOutMsNewProcess);

                                if (!holdsMutex)
                                {
                                    return(Task.FromResult <BuildResponse>(null));
                                }
                            }
                            catch (AbandonedMutexException)
                            {
                                holdsMutex = true;
                            }
                        }

                        // Check for an already running server
                        var   serverMutexName = $"{pipeName}.server";
                        Mutex mutexIgnore;
                        bool  wasServerRunning = Mutex.TryOpenExisting(serverMutexName, out mutexIgnore);
                        var   timeout          = wasServerRunning ? TimeOutMsExistingProcess : TimeOutMsNewProcess;

                        NamedPipeClientStream pipe = null;

                        if (wasServerRunning || TryCreateServerProcess(clientDir, pipeName))
                        {
                            pipe = TryConnectToProcess(pipeName,
                                                       timeout,
                                                       cancellationToken);
                        }

                        if (pipe != null)
                        {
                            var request = BuildRequest.Create(language,
                                                              workingDir,
                                                              arguments,
                                                              keepAlive,
                                                              libEnvVariable);

                            return(TryCompile(pipe, request, cancellationToken));
                        }
                    }
                    finally
                    {
                        if (holdsMutex)
                        {
                            clientMutex.ReleaseMutex();
                        }
                    }
                }
            }
            // Swallow all unhandled exceptions from server compilation. If
            // they are show-stoppers then they will crash the in-proc
            // compilation as well
            // TODO: Put in non-fatal Watson code so we still get info
            // when things unexpectedly fail
            catch { }
            return(Task.FromResult <BuildResponse>(null));
        }
Ejemplo n.º 32
0
        internal static async Task <BuildResponse> RunServerCompilationCoreAsync(
            Guid requestId,
            RequestLanguage language,
            List <string> arguments,
            BuildPathsAlt buildPaths,
            string?pipeName,
            string?keepAlive,
            string?libDirectory,
            int?timeoutOverride,
            CreateServerFunc createServerFunc,
            ICompilerServerLogger logger,
            CancellationToken cancellationToken
            )
        {
            if (pipeName is null)
            {
                throw new ArgumentException(nameof(pipeName));
            }

            if (buildPaths.TempDirectory == null)
            {
                throw new ArgumentException(nameof(buildPaths));
            }

            // early check for the build hash. If we can't find it something is wrong; no point even trying to go to the server
            if (string.IsNullOrWhiteSpace(BuildProtocolConstants.GetCommitHash()))
            {
                return(new IncorrectHashBuildResponse());
            }

            var pipeTask = tryConnectToServer(
                pipeName,
                buildPaths,
                timeoutOverride,
                createServerFunc,
                logger,
                cancellationToken
                );

            if (pipeTask is null)
            {
                return(new RejectedBuildResponse("Failed to connect to server"));
            }
            else
            {
                using var pipe = await pipeTask.ConfigureAwait(false);

                if (pipe is null)
                {
                    return(new RejectedBuildResponse("Failed to connect to server"));
                }
                else
                {
                    var request = BuildRequest.Create(
                        language,
                        arguments,
                        workingDirectory: buildPaths.WorkingDirectory,
                        tempDirectory: buildPaths.TempDirectory,
                        compilerHash: BuildProtocolConstants.GetCommitHash() ?? "",
                        requestId: requestId,
                        keepAlive: keepAlive,
                        libDirectory: libDirectory
                        );

                    return(await TryCompileAsync(pipe, request, logger, cancellationToken)
                           .ConfigureAwait(false));
                }
            }
Ejemplo n.º 33
0
        /// <summary>
        /// Returns a Task with a null BuildResponse if no server
        /// response was received.
        /// </summary>
        public static Task<BuildResponse> TryRunServerCompilation(
            RequestLanguage language,
            string clientDir,
            string workingDir,
            IList<string> arguments,
            CancellationToken cancellationToken,
            string keepAlive = null,
            string libEnvVariable = null)
        {
            try
            {
                NamedPipeClientStream pipe;

                if (clientDir == null)
                    return Task.FromResult<BuildResponse>(null);

                var pipeName = GetPipeName(clientDir);
                bool holdsMutex;
                using (var mutex = new Mutex(initiallyOwned: true,
                                             name: pipeName,
                                             createdNew: out holdsMutex))
                {
                    try
                    {
                        if (!holdsMutex)
                        {
                            try
                            {
                                holdsMutex = mutex.WaitOne(TimeOutMsNewProcess);
                            }
                            catch (AbandonedMutexException)
                            {
                                holdsMutex = true;
                            }
                        }

                        if (holdsMutex)
                        {
                            var request = BuildRequest.Create(language, workingDir, arguments, keepAlive, libEnvVariable);
                            // Check for already running processes in case someone came in before us
                            string availablePipeName;
                            if (null != (pipe = TryAllProcesses(pipeName,
                                                                TimeOutMsExistingProcess,
                                                                cancellationToken,
                                                                out availablePipeName)))
                            {
                                return TryCompile(pipe, request, cancellationToken);
                            }
                            else
                            {
                                if (TryCreateServerProcess(clientDir, availablePipeName) &&
                                    null != (pipe = TryConnectToProcess(availablePipeName,
                                                                        TimeOutMsNewProcess,
                                                                        cancellationToken)))
                                {
                                    // Let everyone else access our process
                                    mutex.ReleaseMutex();
                                    holdsMutex = false;

                                    return TryCompile(pipe, request, cancellationToken);
                                }
                            }
                        }
                    }
                    finally
                    {
                        if (holdsMutex)
                            mutex.ReleaseMutex();
                    }
                }
            }
            // Swallow all unhandled exceptions from server compilation. If
            // they are show-stoppers then they will crash the in-proc
            // compilation as well
            // TODO: Put in non-fatal Watson code so we still get info
            // when things unexpectedly fail
            catch { }
            return Task.FromResult<BuildResponse>(null);
        }
Ejemplo n.º 34
0
        internal static int Run(IEnumerable <string> arguments, IEnumerable <string> extraArguments, RequestLanguage language, CompileFunc compileFunc, IAnalyzerAssemblyLoader analyzerAssemblyLoader)
        {
            var client            = new DesktopBuildClient(language, compileFunc, analyzerAssemblyLoader);
            var clientDir         = AppDomain.CurrentDomain.BaseDirectory;
            var sdkDir            = RuntimeEnvironment.GetRuntimeDirectory();
            var workingDir        = Directory.GetCurrentDirectory();
            var buildPaths        = new BuildPaths(clientDir: clientDir, workingDir: workingDir, sdkDir: sdkDir);
            var originalArguments = BuildClient.GetCommandLineArgs(arguments).Concat(extraArguments).ToArray();

            return(client.RunCompilation(originalArguments, buildPaths).ExitCode);
        }
Ejemplo n.º 35
0
 private CoreClrBuildClient(RequestLanguage language, CompileFunc compileFunc)
 {
     _language = language;
     _compileFunc = compileFunc;
 }
        internal static async Task <BuildResponse> RunServerCompilationCore(
            RequestLanguage language,
            List <string> arguments,
            BuildPathsAlt buildPaths,
            string pipeName,
            string keepAlive,
            string libEnvVariable,
            int?timeoutOverride,
            Func <string, string, bool> tryCreateServerFunc,
            CancellationToken cancellationToken)
        {
            if (pipeName == null)
            {
                return(new RejectedBuildResponse());
            }

            if (buildPaths.TempDirectory == null)
            {
                return(new RejectedBuildResponse());
            }

            // early check for the build hash. If we can't find it something is wrong; no point even trying to go to the server
            if (string.IsNullOrWhiteSpace(BuildProtocolConstants.GetCommitHash()))
            {
                return(new IncorrectHashBuildResponse());
            }

            var clientDir                         = buildPaths.ClientDirectory;
            var timeoutNewProcess                 = timeoutOverride ?? TimeOutMsNewProcess;
            var timeoutExistingProcess            = timeoutOverride ?? TimeOutMsExistingProcess;
            Task <NamedPipeClientStream> pipeTask = null;
            Mutex clientMutex                     = null;
            var   holdsMutex                      = false;

            try
            {
                try
                {
                    var clientMutexName = GetClientMutexName(pipeName);
                    clientMutex = new Mutex(initiallyOwned: true, name: clientMutexName, out holdsMutex);
                }
                catch
                {
                    // The Mutex constructor can throw in certain cases. One specific example is docker containers
                    // where the /tmp directory is restricted. In those cases there is no reliable way to execute
                    // the server and we need to fall back to the command line.
                    //
                    // Example: https://github.com/dotnet/roslyn/issues/24124
                    return(new RejectedBuildResponse());
                }

                if (!holdsMutex)
                {
                    try
                    {
                        holdsMutex = clientMutex.WaitOne(timeoutNewProcess);

                        if (!holdsMutex)
                        {
                            return(new RejectedBuildResponse());
                        }
                    }
                    catch (AbandonedMutexException)
                    {
                        holdsMutex = true;
                    }
                }

                // Check for an already running server
                var  serverMutexName  = GetServerMutexName(pipeName);
                bool wasServerRunning = WasServerMutexOpen(serverMutexName);
                var  timeout          = wasServerRunning ? timeoutExistingProcess : timeoutNewProcess;

                if (wasServerRunning || tryCreateServerFunc(clientDir, pipeName))
                {
                    pipeTask = TryConnectToServerAsync(pipeName, timeout, cancellationToken);
                }
            }
            finally
            {
                if (clientMutex != null)
                {
                    if (holdsMutex)
                    {
                        clientMutex.ReleaseMutex();
                    }
                    clientMutex.Dispose();
                }
            }

            if (pipeTask != null)
            {
                var pipe = await pipeTask.ConfigureAwait(false);

                if (pipe != null)
                {
                    var request = BuildRequest.Create(language,
                                                      buildPaths.WorkingDirectory,
                                                      buildPaths.TempDirectory,
                                                      BuildProtocolConstants.GetCommitHash(),
                                                      arguments,
                                                      keepAlive,
                                                      libEnvVariable);

                    return(await TryCompile(pipe, request, cancellationToken).ConfigureAwait(false));
                }
            }

            return(new RejectedBuildResponse());
        }
Ejemplo n.º 37
0
        internal static async Task <BuildResponse> RunServerCompilationCore(
            RequestLanguage language,
            List <string> arguments,
            BuildPathsAlt buildPaths,
            string pipeName,
            string keepAlive,
            string libEnvVariable,
            int?timeoutOverride,
            Func <string, string, bool> tryCreateServerFunc,
            CancellationToken cancellationToken)
        {
            if (pipeName == null)
            {
                return(new RejectedBuildResponse());
            }

            if (buildPaths.TempDirectory == null)
            {
                return(new RejectedBuildResponse());
            }

            var clientDir                         = buildPaths.ClientDirectory;
            var timeoutNewProcess                 = timeoutOverride ?? TimeOutMsNewProcess;
            var timeoutExistingProcess            = timeoutOverride ?? TimeOutMsExistingProcess;
            var clientMutexName                   = GetClientMutexName(pipeName);
            Task <NamedPipeClientStream> pipeTask = null;

            using (var clientMutex = new Mutex(initiallyOwned: true,
                                               name: clientMutexName,
                                               createdNew: out var holdsMutex))
            {
                try
                {
                    if (!holdsMutex)
                    {
                        try
                        {
                            holdsMutex = clientMutex.WaitOne(timeoutNewProcess);

                            if (!holdsMutex)
                            {
                                return(new RejectedBuildResponse());
                            }
                        }
                        catch (AbandonedMutexException)
                        {
                            holdsMutex = true;
                        }
                    }

                    // Check for an already running server
                    var  serverMutexName  = GetServerMutexName(pipeName);
                    bool wasServerRunning = WasServerMutexOpen(serverMutexName);
                    var  timeout          = wasServerRunning ? timeoutExistingProcess : timeoutNewProcess;

                    if (wasServerRunning || tryCreateServerFunc(clientDir, pipeName))
                    {
                        pipeTask = TryConnectToServerAsync(pipeName, timeout, cancellationToken);
                    }
                }
                finally
                {
                    if (holdsMutex)
                    {
                        clientMutex.ReleaseMutex();
                    }
                }
            }

            if (pipeTask != null)
            {
                var pipe = await pipeTask.ConfigureAwait(false);

                if (pipe != null)
                {
                    var request = BuildRequest.Create(language,
                                                      buildPaths.WorkingDirectory,
                                                      buildPaths.TempDirectory,
                                                      arguments,
                                                      keepAlive,
                                                      libEnvVariable);

                    return(await TryCompile(pipe, request, cancellationToken).ConfigureAwait(false));
                }
            }

            return(new RejectedBuildResponse());
        }
Ejemplo n.º 38
0
        public async Task <AccountInfoHistoryResponse> GetAccountInfoHistory(RealmType realm, long accountId, DateTime startDate, RequestLanguage requestLanguage)
        {
            var contextData = new AccountHistoryInformationPipelineContextData(startDate);

            try
            {
                var context = new OperationContext(new AccountRequest(accountId, realm, requestLanguage));
                context.AddOrReplace(contextData);
                var pipeline = new Pipeline <IOperationContext>(_operationFactory);

                pipeline.AddOperation <ReadAccountInfoFromDbOperation>()
                .AddOperation <ReadAccountInfoHistoryFromDbOperation>()
                .AddOperation <CheckIfHistoryIsEmptyOperation>()
                .AddOperation <FillOverallStatisticsOperation>()
                .AddOperation <FillPeriodStatisticsOperation>()
                .AddOperation <FillPeriodDifferenceOperation>()
                .AddOperation <FillStatisticsDifferenceOperation>()
                .AddOperation <FillAccountInfoHistoryResponse>()
                ;

                var firstOperation = pipeline.Build();
                if (firstOperation != null)
                {
                    await firstOperation
                    .Invoke(context, null)
                    .ConfigureAwait(false);
                }
            }
            catch (Exception e)
            {
                _logger.LogError(e, "GetAccountInfoHistory error");
                throw;
            }
            return(contextData?.Response ?? new AccountInfoHistoryResponse());
        }