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()); }
public static Task<BuildResponse> RunServerCompilation( RequestLanguage language, List<string> arguments, BuildPaths buildPaths, string keepAlive, string libEnvVariable, CancellationToken cancellationToken) => Task.FromResult<BuildResponse>(null);
public TestableDesktopBuildClient( RequestLanguage langauge, CompileFunc compileFunc, string pipeName, Func<string, bool> createServerFunc) : base(langauge, compileFunc, new Mock<IAnalyzerAssemblyLoader>().Object) { _pipeName = pipeName; _createServerFunc = createServerFunc; }
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); }
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; }
public static Task<BuildResponse> RunServerCompilation( RequestLanguage language, List<string> arguments, BuildPaths buildPaths, string keepAlive, string libEnvVariable, CancellationToken cancellationToken) { throw new NotSupportedException(); }
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); }
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; }
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);
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; }
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."); } }
/// <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); }
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); }
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); }
internal DesktopBuildClient(RequestLanguage language, CompileFunc compileFunc, IAnalyzerAssemblyLoader analyzerAssemblyLoader) { _language = language; _compileFunc = compileFunc; _analyzerAssemblyLoader = analyzerAssemblyLoader; }
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; }
/// <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)); }
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); }
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); }
/// <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); }
internal BuildClient(RequestLanguage language, CompileFunc compileFunc, CompileOnServerFunc compileOnServerFunc) { _language = language; _compileFunc = compileFunc; _compileOnServerFunc = compileOnServerFunc; }
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); }
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); }
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); }
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()); }
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); }
private CoreClrBuildClient(RequestLanguage language, CompileFunc compileFunc) { _language = language; _compileFunc = compileFunc; }
/// <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)); }
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)); }
/// <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)); }
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)); } }
/// <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); }
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); }
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()); }
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()); }
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()); }