/// <summary> /// An incoming request as occurred. This is called on a new thread to handle /// the request. /// </summary> public BuildResponse HandleRequest(BuildRequest req, CancellationToken cancellationToken) { switch (req.Language) { case BuildProtocolConstants.RequestLanguage.CSharpCompile: CompilerServerLogger.Log("Request to compile C#"); return CSharpCompile(req, cancellationToken); case BuildProtocolConstants.RequestLanguage.VisualBasicCompile: CompilerServerLogger.Log("Request to compile VB"); return BasicCompile(req, cancellationToken); default: CompilerServerLogger.Log("Got request with id '{0}'", req.Language); for (int i = 0; i < req.Arguments.Length; ++i) { CompilerServerLogger.Log("Request argument '{0}[{1}]' = '{2}'", req.Arguments[i].ArgumentId, req.Arguments[i].ArgumentIndex, req.Arguments[i].Value); } // We can't do anything with a request we don't know about. return new CompletedBuildResponse(-1, utf8output: false, output: "", errorOutput: ""); } }
public async Task<BuildResponse> GetResponseAsync(BuildRequest req, CancellationToken cancellationToken) { NamedPipeClientStream pipeStream; if (TryAutoConnectToServer(cancellationToken, out pipeStream)) { // We have a good connection BuildResponse response = await DoCompilationAsync(pipeStream, req, cancellationToken).ConfigureAwait(false); if (response != null) { return response; } else { CompilerServerLogger.Log("Compilation failed, constructing new compiler server"); // The compilation failed. There are a couple possible reasons for this, // including that we are using a 32-bit compiler server and we are out of // memory. This is the last attempt -- we will create a new server manually // and try to compile. There is no mutex because anyone else using // this server is accidental only. int newProcessId = CreateNewServerProcess(); if (newProcessId != 0 && TryConnectToProcess(newProcessId, TimeOutMsNewProcess, cancellationToken, out pipeStream)) { return await DoCompilationAsync(pipeStream, req, cancellationToken).ConfigureAwait(false); } } } return null; }
private static string[] GetCommandLineArguments(BuildRequest req, out string currentDirectory, out string libDirectory) { currentDirectory = null; libDirectory = null; List<string> commandLineArguments = new List<string>(); foreach (BuildRequest.Argument arg in req.Arguments) { if (arg.ArgumentId == BuildProtocolConstants.ArgumentId_CurrentDirectory) { currentDirectory = arg.Value; } else if (arg.ArgumentId == BuildProtocolConstants.ArgumentId_LibEnvVariable) { libDirectory = arg.Value; } else if (arg.ArgumentId == BuildProtocolConstants.ArgumentId_CommandLineArgument) { uint argIndex = arg.ArgumentIndex; while (argIndex >= commandLineArguments.Count) commandLineArguments.Add(""); commandLineArguments[(int)argIndex] = arg.Value; } } return commandLineArguments.ToArray(); }
/// <summary> /// An incoming request as occurred. This is called on a new thread to handle /// the request. /// </summary> public BuildResponse HandleRequest(BuildRequest req, CancellationToken cancellationToken) { switch (req.Id) { case BuildProtocolConstants.RequestId_CSharpCompile: CompilerServerLogger.Log("Request to compile C#"); return CSharpCompile(req, cancellationToken); case BuildProtocolConstants.RequestId_VisualBasicCompile: CompilerServerLogger.Log("Request to compile VB"); return BasicCompile(req, cancellationToken); case BuildProtocolConstants.RequestId_Analyze: CompilerServerLogger.Log("Request to analyze managed code"); return Analyze(req, cancellationToken); default: CompilerServerLogger.Log("Got request with id '{0}'", req.Id); for (int i = 0; i < req.Arguments.Length; ++i) { CompilerServerLogger.Log("Request argument '{0}[{1}]' = '{2}'", req.Arguments[i].ArgumentId, req.Arguments[i].ArgumentIndex, req.Arguments[i].Value); } // We can't do anything with a request we don't know about. return new BuildResponse(0, "", ""); } }
internal static int ExecuteTool(BuildRequest request, CancellationToken cancellationToken, out bool canceled, out string output, out string errorOutput) { canceled = false; BuildClient client = new BuildClient(); Task<BuildResponse> responseTask = client.GetResponseAsync(request, cancellationToken); BuildResponse response = null; try { responseTask.Wait(cancellationToken); response = responseTask.Result; } catch (OperationCanceledException) { canceled = true; output = null; errorOutput = null; return 0; } catch (AggregateException ae) { CompilerServerLogger.LogException(ae, "Unexpected failure."); foreach (var e in ae.InnerExceptions) { CompilerServerLogger.LogException(e, ""); } } if (response == null) { output = null; errorOutput = "Fatal Error: Please see the event log for more details."; return -1; } output = response.Output; errorOutput = response.ErrorOutput; return response.ReturnCode; }
public async Task <ConnectionData> HandleConnection(bool allowCompilationRequests = true, CancellationToken cancellationToken = default(CancellationToken)) { try { BuildRequest request; try { Log("Begin reading request."); request = await BuildRequest.ReadAsync(_stream, cancellationToken).ConfigureAwait(false); ValidateBuildRequest(request); Log("End reading request."); } catch (Exception e) { LogException(e, "Error reading build request."); return(new ConnectionData(CompletionReason.CompilationNotStarted)); } if (IsShutdownRequest(request)) { return(await HandleShutdownRequest(cancellationToken).ConfigureAwait(false)); } else if (!allowCompilationRequests) { return(await HandleRejectedRequest(cancellationToken).ConfigureAwait(false)); } else { return(await HandleCompilationRequest(request, cancellationToken).ConfigureAwait(false)); } } finally { Close(); } }
internal static string[] GetCommandLineArguments(BuildRequest req, out string?currentDirectory, out string?tempDirectory, out string?libDirectory) { currentDirectory = null; libDirectory = null; tempDirectory = null; List <string> commandLineArguments = new List <string>(); foreach (BuildRequest.Argument arg in req.Arguments) { if (arg.ArgumentId == BuildProtocolConstants.ArgumentId.CurrentDirectory) { currentDirectory = arg.Value; } else if (arg.ArgumentId == BuildProtocolConstants.ArgumentId.TempDirectory) { tempDirectory = arg.Value; } else if (arg.ArgumentId == BuildProtocolConstants.ArgumentId.LibEnvVariable) { libDirectory = arg.Value; } else if (arg.ArgumentId == BuildProtocolConstants.ArgumentId.CommandLineArgument) { if (arg.Value is object) { int argIndex = arg.ArgumentIndex; while (argIndex >= commandLineArguments.Count) { commandLineArguments.Add(""); } commandLineArguments[argIndex] = arg.Value; } } } return(commandLineArguments.ToArray()); }
/// <summary> /// A request to compile VB files. Unpack the arguments and current directory and invoke /// the compiler, then create a response with the result of compilation. /// </summary> private BuildResponse BasicCompile(BuildRequest req, CancellationToken cancellationToken) { string currentDirectory; string libDirectory; string tempPath; var commandLineArguments = GetCommandLineArguments(req, out currentDirectory, out libDirectory, out tempPath); if (currentDirectory == null) { // If we don't have a current directory, compilation can't proceed. This shouldn't ever happen, // because our clients always send the current directory. Debug.Assert(false, "Client did not send current directory; this is required."); return(new CompletedBuildResponse(-1, utf8output: false, output: "", errorOutput: "")); } if (tempPath == null) { // If we don't have a temp directory, compilation can't proceed. This shouldn't ever happen, // because our clients always send the temp directory. Debug.Assert(false, "Client did not send temp directory; this is required."); return(new CompletedBuildResponse(-1, utf8output: false, output: "", errorOutput: "")); } TextWriter output = new StringWriter(CultureInfo.InvariantCulture); bool utf8output; int returnCode = BasicCompile( _responseFileDirectory, currentDirectory, libDirectory, tempPath, commandLineArguments, output, cancellationToken, out utf8output); return(new CompletedBuildResponse(returnCode, utf8output, output.ToString(), "")); }
private BuildResponse ServeBuildRequestCore(BuildRequest buildRequest, CancellationToken cancellationToken) { var request = BuildProtocolUtil.GetRunRequest(buildRequest); CommonCompiler compiler; if (!_compilerServerHost.TryCreateCompiler(request, out compiler)) { // TODO: is this the right option? Right now it will cause the fall back in the command line // to fail because it's a valid response. Probably should add a "server failed" response // for command line to deal with. // We can't do anything with a request we don't know about. Log($"Got request with id '{request.Language}'"); return(new CompletedBuildResponse(-1, false, "", "")); } Log($"CurrentDirectory = '{request.CurrentDirectory}'"); Log($"LIB = '{request.LibDirectory}'"); for (int i = 0; i < request.Arguments.Length; ++i) { Log($"Argument[{i}] = '{request.Arguments[i]}'"); } bool utf8output = compiler.Arguments.Utf8Output; if (!_compilerServerHost.CheckAnalyzers(request.CurrentDirectory, compiler.Arguments.AnalyzerReferences)) { return(new AnalyzerInconsistencyBuildResponse()); } Log($"****Running {request.Language} compiler..."); TextWriter output = new StringWriter(CultureInfo.InvariantCulture); int returnCode = compiler.Run(output, cancellationToken); Log($"****{request.Language} Compilation complete.\r\n****Return code: {returnCode}\r\n****Output:\r\n{output.ToString()}\r\n"); return(new CompletedBuildResponse(returnCode, utf8output, output.ToString(), "")); }
/// <summary> /// A request to compile C# files. Unpack the arguments and current directory and invoke /// the compiler, then create a response with the result of compilation. /// </summary> private BuildResponse CSharpCompile(BuildRequest req, CancellationToken cancellationToken) { string currentDirectory; string libDirectory; var commandLineArguments = GetCommandLineArguments(req, out currentDirectory, out libDirectory); if (currentDirectory == null) { // If we don't have a current directory, compilation can't proceed. This shouldn't ever happen, // because our clients always send the current directory. Debug.Assert(false, "Client did not send current directory; this is required."); return(new CompletedBuildResponse(-1, utf8output: false, output: "", errorOutput: "")); } return(CSharpCompile( currentDirectory, libDirectory, _responseFileDirectory, commandLineArguments, cancellationToken)); }
public async Task ServeConnection() { BuildRequest request; try { Log("Begin reading request"); request = await BuildRequest.ReadAsync(pipeStream, cancellationTokenSource.Token).ConfigureAwait(false); Log("End reading request"); } catch (IOException e) { LogException(e, "Reading request from named pipe."); FinishConnection(CompletionReason.IOFailure); return; } catch (OperationCanceledException e) { LogException(e, "Reading request from named pipe."); FinishConnection(CompletionReason.Cancelled); return; } if (!ClientAndOurIdentitiesMatch(pipeStream)) { Log("Client identity doesn't match."); FinishConnection(CompletionReason.SecurityViolation); return; } CheckForNewKeepAlive(request); // Start a monitor that cancels if the pipe closes on us var _ = MonitorPipeForDisconnection().ConfigureAwait(false); // Do the compilation Log("Begin compilation"); BuildResponse response = await Task.Run(() => { try { return(handler.HandleRequest(request, cancellationTokenSource.Token)); } catch (Exception e) if (CompilerFatalError.ReportUnlessCanceled(e)) { throw ExceptionUtilities.Unreachable; } }).ConfigureAwait(false); Log("End compilation"); try { Log("Begin writing response"); await response.WriteAsync(pipeStream, cancellationTokenSource.Token).ConfigureAwait(false); Log("End writing response"); } catch (IOException e) { LogException(e, "Writing response to named pipe."); FinishConnection(CompletionReason.IOFailure); return; } catch (OperationCanceledException e) { LogException(e, "Writing response to named pipe."); FinishConnection(CompletionReason.Cancelled); return; } Log("Completed writing response to named pipe."); FinishConnection(CompletionReason.Success); }
/// <summary> /// Try to compile using the server. Returns null if a response from the /// server cannot be retrieved. /// </summary> private static async Task<BuildResponse> TryCompile(NamedPipeClientStream pipeStream, BuildRequest request, CancellationToken cancellationToken) { BuildResponse response; using (pipeStream) { // Write the request try { Log("Begin writing request"); await request.WriteAsync(pipeStream, cancellationToken).ConfigureAwait(false); Log("End writing request"); } catch (Exception e) { LogException(e, "Error writing build request."); return null; } // Wait for the compilation and a monitor to detect if the server disconnects var serverCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); Log("Begin reading response"); var responseTask = BuildResponse.ReadAsync(pipeStream, serverCts.Token); var monitorTask = CreateMonitorDisconnectTask(pipeStream, serverCts.Token); await Task.WhenAny(responseTask, monitorTask).ConfigureAwait(false); Log("End reading response"); if (responseTask.IsCompleted) { // await the task to log any exceptions try { response = await responseTask.ConfigureAwait(false); } catch (Exception e) { LogException(e, "Error reading response"); response = null; } } else { Log("Server disconnect"); response = null; } // Cancel whatever task is still around serverCts.Cancel(); return response; } }
private async Task <CompletionData> ProcessCompilationRequestAsync(IClientConnection clientConnection, BuildRequest request, CancellationToken cancellationToken) { // Need to wait for the compilation and client disconnection in parallel. If the client // suddenly disconnects we need to cancel the compilation that is occuring. It could be the // client hit Ctrl-C due to a run away analyzer. var buildCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); var compilationTask = ProcessCompilationRequestCore(CompilerServerHost, request, buildCancellationTokenSource.Token); await Task.WhenAny(compilationTask, clientConnection.DisconnectTask).ConfigureAwait(false); try { if (compilationTask.IsCompleted) { BuildResponse response; try { response = await compilationTask.ConfigureAwait(false); } catch (Exception ex) { CompilerServerLogger.LogException(ex, $"Exception running compilation for {clientConnection.LoggingIdentifier}"); response = new RejectedBuildResponse($"Exception during compilation: {ex.Message}"); } await clientConnection.WriteBuildResponseAsync(response, cancellationToken).ConfigureAwait(false); var newKeepAlive = CheckForNewKeepAlive(request); var completionReason = response switch { AnalyzerInconsistencyBuildResponse _ => CompletionReason.RequestError, RejectedBuildResponse _ => CompletionReason.RequestError, _ => CompletionReason.RequestCompleted }; return(new CompletionData(completionReason, newKeepAlive)); } else { return(CompletionData.RequestError); } } finally { buildCancellationTokenSource.Cancel(); }
static Task <BuildResponse> ProcessCompilationRequestCore(ICompilerServerHost compilerServerHost, BuildRequest buildRequest, CancellationToken cancellationToken) { Func <BuildResponse> func = () => { var request = BuildProtocolUtil.GetRunRequest(buildRequest); var response = compilerServerHost.RunCompilation(request, cancellationToken); return(response); }; var task = new Task <BuildResponse>(func, cancellationToken, TaskCreationOptions.LongRunning); task.Start(); return(task); }
private async Task <CompletionData> ProcessCompilationRequestAsync(IClientConnection clientConnection, BuildRequest request, CancellationToken cancellationToken) { // Need to wait for the compilation and client disconnection in parallel. If the client // suddenly disconnects we need to cancel the compilation that is occuring. It could be the // client hit Ctrl-C due to a run away analyzer. var buildCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); var compilationTask = ProcessCompilationRequestCore(CompilerServerHost, request, buildCancellationTokenSource.Token); await Task.WhenAny(compilationTask, clientConnection.DisconnectTask).ConfigureAwait(false); try { if (compilationTask.IsCompleted) { BuildResponse response; CompletionData completionData; try { response = await compilationTask.ConfigureAwait(false); completionData = response switch { // Once there is an analyzer inconsistency the assembly load space is polluted. The // request is an error. AnalyzerInconsistencyBuildResponse _ => CompletionData.RequestError, _ => new CompletionData(CompletionReason.RequestCompleted, newKeepAlive: CheckForNewKeepAlive(request)) }; } catch (Exception ex) { // The compilation task should never throw. If it does we need to assume that the compiler is // in a bad state and need to issue a RequestError CompilerServerLogger.LogException(ex, $"Exception running compilation for {clientConnection.LoggingIdentifier}"); response = new RejectedBuildResponse($"Exception during compilation: {ex.Message}"); completionData = CompletionData.RequestError; } return(await WriteBuildResponseAsync( clientConnection, response, completionData, cancellationToken).ConfigureAwait(false)); } else { return(CompletionData.RequestError); } } finally { buildCancellationTokenSource.Cancel(); }
private Task<BuildResponse> ServeBuildRequest(BuildRequest request, CancellationToken cancellationToken) { return Task.Run(() => { try { // Do the compilation Log("Begin compilation"); BuildResponse response = _handler.HandleRequest(request, cancellationToken); Log("End compilation"); return response; } catch (Exception e) when (FatalError.Report(e)) { throw ExceptionUtilities.Unreachable; } }); }
/// <summary> /// Shutting down the server is an inherently racy operation. The server can be started or stopped by /// external parties at any time. /// /// This function will return success if at any time in the function the server is determined to no longer /// be running. /// </summary> internal async Task <int> RunShutdownAsync( string pipeName, bool waitForProcess = true, TimeSpan?timeout = null, CancellationToken cancellationToken = default ) { if (WasServerRunning(pipeName) == false) { // The server holds the mutex whenever it is running, if it's not open then the // server simply isn't running. return(CommonCompiler.Succeeded); } try { var realTimeout = timeout != null ? (int)timeout.Value.TotalMilliseconds : Timeout.Infinite; using var client = await ConnectForShutdownAsync(pipeName, realTimeout) .ConfigureAwait(false); if (client is object) { var request = BuildRequest.CreateShutdown(); await request.WriteAsync(client, cancellationToken).ConfigureAwait(false); var response = await BuildResponse .ReadAsync(client, cancellationToken) .ConfigureAwait(false); var shutdownResponse = (ShutdownBuildResponse)response; if (waitForProcess) { try { var process = Process.GetProcessById(shutdownResponse.ServerProcessId); process.WaitForExit(); } catch (Exception) { // There is an inherent race here with the server process. If it has already shutdown // by the time we try to access it then the operation has succeed. } } } return(CommonCompiler.Succeeded); } catch (Exception) { if (WasServerRunning(pipeName) == false) { // If the server was in the process of shutting down when we connected then it's reasonable // for an exception to happen. If the mutex has shutdown at this point then the server // is shut down. return(CommonCompiler.Succeeded); } return(CommonCompiler.Failed); } }
/// <summary> /// A request to analyze managed source code files. Unpack the arguments and current directory and invoke /// the analyzer, then create a response with the result of compilation. /// </summary> private BuildResponse Analyze(BuildRequest req, CancellationToken cancellationToken) { string currentDirectory; string libDirectory; var commandLineArguments = GetCommandLineArguments(req, out currentDirectory, out libDirectory); // Server based execution of Roslyn Diagnostic Providers (Disabled for now). throw new NotImplementedException("Server based execution of Roslyn Diagnostic Providers NYI."); // TextWriter output = new StringWriter(CultureInfo.InvariantCulture); // var task = Microsoft.CodeAnalysis.Diagnostics.CommandLineDiagnosticService.ComputeAndWriteDiagnosticsAsync(commandLineArguments, output, cancellationToken); // task.Wait(cancellationToken); // int returnCode = task.Result; // return new BuildResponse(returnCode, "", output.ToString()); }
protected virtual void ValidateBuildRequest(BuildRequest request) { }
/// <summary> /// A request to compile VB files. Unpack the arguments and current directory and invoke /// the compiler, then create a response with the result of compilation. /// </summary> private BuildResponse BasicCompile(BuildRequest req, CancellationToken cancellationToken) { string currentDirectory; string libDirectory; var commandLineArguments = GetCommandLineArguments(req, out currentDirectory, out libDirectory); if (currentDirectory == null) { // If we don't have a current directory, compilation can't proceed. This shouldn't ever happen, // because our clients always send the current directory. Debug.Assert(false, "Client did not send current directory; this is required."); return new CompletedBuildResponse(-1, utf8output: false, output: "", errorOutput: ""); } return BasicCompile( _responseFileDirectory, currentDirectory, libDirectory, commandLineArguments, cancellationToken); }
public async Task <ConnectionData> HandleConnection(CancellationToken cancellationToken) { try { BuildRequest request; try { Log("Begin reading request."); request = await BuildRequest.ReadAsync(_stream, cancellationToken).ConfigureAwait(false); ValidateBuildRequest(request); Log("End reading request."); } catch (Exception e) { LogException(e, "Error reading build request."); return(new ConnectionData(CompletionReason.CompilationNotStarted)); } var keepAlive = CheckForNewKeepAlive(request); // Kick off both the compilation and a task to monitor the pipe for closing. var buildCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); var compilationTask = ServeBuildRequest(request, buildCts.Token); var monitorTask = CreateMonitorDisconnectTask(buildCts.Token); await Task.WhenAny(compilationTask, monitorTask).ConfigureAwait(false); // Do an 'await' on the completed task, preference being compilation, to force // any exceptions to be realized in this method for logging. CompletionReason reason; if (compilationTask.IsCompleted) { var response = await compilationTask.ConfigureAwait(false); try { Log("Begin writing response."); await response.WriteAsync(_stream, cancellationToken).ConfigureAwait(false); reason = CompletionReason.Completed; Log("End writing response."); } catch { reason = CompletionReason.ClientDisconnect; } } else { await monitorTask.ConfigureAwait(false); reason = CompletionReason.ClientDisconnect; } // Begin the tear down of the Task which didn't complete. buildCts.Cancel(); return(new ConnectionData(reason, keepAlive)); } finally { Close(); } }
private async Task<BuildResponse> DoCompilationAsync(NamedPipeClientStream pipeStream, BuildRequest req, CancellationToken cancellationToken) { using (pipeStream) { try { // Start a monitor that cancels if the pipe closes on us var monitorCancellation = new CancellationTokenSource(); Task disconnectMonitor = MonitorPipeForDisconnectionAsync(pipeStream, monitorCancellation.Token); // Write the request. CompilerServerLogger.Log("Writing request"); await req.WriteAsync(pipeStream, cancellationToken).ConfigureAwait(false); // Read the response. CompilerServerLogger.Log("Reading response"); BuildResponse response = await BuildResponse.ReadAsync(pipeStream, cancellationToken).ConfigureAwait(false); // Stop monitoring pipe monitorCancellation.Cancel(throwOnFirstException: true); await disconnectMonitor.ConfigureAwait(false); Debug.Assert(response != null); CompilerServerLogger.Log("BuildResponse received; exit code={0}", response.ReturnCode); return response; } catch (PipeBrokenException e) { CompilerServerLogger.LogException(e, "Server process died; pipe broken."); return null; } catch (ObjectDisposedException e) { CompilerServerLogger.LogException(e, "Pipe stream unexpectedly disposed"); return null; } } }
/// <summary> /// Shutting down the server is an inherently racy operation. The server can be started or stopped by /// external parties at any time. /// /// This function will return success if at any time in the function the server is determined to no longer /// be running. /// </summary> internal static async Task <int> RunShutdownAsync(string pipeName, bool waitForProcess = true, TimeSpan?timeout = null, CancellationToken cancellationToken = default(CancellationToken)) { if (string.IsNullOrEmpty(pipeName)) { var clientDirectory = AppDomain.CurrentDomain.BaseDirectory; pipeName = DesktopBuildClient.GetPipeNameFromFileInfo(clientDirectory); } var mutexName = BuildProtocolConstants.GetServerMutexName(pipeName); if (!DesktopBuildClient.WasServerMutexOpen(mutexName)) { // The server holds the mutex whenever it is running, if it's not open then the // server simply isn't running. return(CommonCompiler.Succeeded); } try { using (var client = new NamedPipeClientStream(pipeName)) { var realTimeout = timeout != null ? (int)timeout.Value.TotalMilliseconds : Timeout.Infinite; client.Connect(realTimeout); var request = BuildRequest.CreateShutdown(); await request.WriteAsync(client, cancellationToken).ConfigureAwait(false); var response = await BuildResponse.ReadAsync(client, cancellationToken).ConfigureAwait(false); var shutdownResponse = (ShutdownBuildResponse)response; if (waitForProcess) { try { var process = Process.GetProcessById(shutdownResponse.ServerProcessId); process.WaitForExit(); } catch (Exception) { // There is an inherent race here with the server process. If it has already shutdown // by the time we try to access it then the operation has succeed. } } } return(CommonCompiler.Succeeded); } catch (Exception) { if (!DesktopBuildClient.WasServerMutexOpen(mutexName)) { // If the server was in the process of shutting down when we connected then it's reasonable // for an exception to happen. If the mutex has shutdown at this point then the server // is shut down. return(CommonCompiler.Succeeded); } return(CommonCompiler.Failed); } }
/// <summary> /// A request to compile C# files. Unpack the arguments and current directory and invoke /// the compiler, then create a response with the result of compilation. /// </summary> private BuildResponse CSharpCompile(BuildRequest req, CancellationToken cancellationToken) { string currentDirectory; string libDirectory; var commandLineArguments = GetCommandLineArguments(req, out currentDirectory, out libDirectory); if (currentDirectory == null) { // If we don't have a current directory, compilation can't proceed. This shouldn't ever happen, // because our clients always send the current directory. Debug.Assert(false, "Client did not send current directory; this is required."); return new BuildResponse(-1, "", ""); } TextWriter output = new StringWriter(CultureInfo.InvariantCulture); int returnCode = CSharpCompile(currentDirectory, libDirectory, commandLineArguments, output, cancellationToken); return new BuildResponse(returnCode, output.ToString(), ""); }
/// <summary> /// Check the request arguments for a new keep alive time. If one is present, /// set the server timer to the new time. /// </summary> private void CheckForNewKeepAlive(BuildRequest request, TaskCompletionSource<TimeSpan?> timeoutCompletionSource) { TimeSpan? timeout = null; foreach (var arg in request.Arguments) { if (arg.ArgumentId == BuildProtocolConstants.ArgumentId.KeepAlive) { int result; // If the value is not a valid integer for any reason, // ignore it and continue with the current timeout. The client // is responsible for validating the argument. if (int.TryParse(arg.Value, out result)) { // Keep alive times are specified in seconds timeout = TimeSpan.FromSeconds(result); } } } timeoutCompletionSource.SetResult(timeout); }
private bool IsShutdownRequest(BuildRequest request) { return(request.Arguments.Count == 1 && request.Arguments[0].ArgumentId == BuildProtocolConstants.ArgumentId.Shutdown); }
/// <summary> /// A request to compile VB files. Unpack the arguments and current directory and invoke /// the compiler, then create a response with the result of compilation. /// </summary> private BuildResponse BasicCompile(BuildRequest req, CancellationToken cancellationToken) { string currentDirectory; string libDirectory; string tempPath; var commandLineArguments = GetCommandLineArguments(req, out currentDirectory, out libDirectory, out tempPath); if (currentDirectory == null) { // If we don't have a current directory, compilation can't proceed. This shouldn't ever happen, // because our clients always send the current directory. Debug.Assert(false, "Client did not send current directory; this is required."); return new CompletedBuildResponse(-1, utf8output: false, output: "", errorOutput: ""); } if (tempPath == null) { // If we don't have a temp directory, compilation can't proceed. This shouldn't ever happen, // because our clients always send the temp directory. Debug.Assert(false, "Client did not send temp directory; this is required."); return new CompletedBuildResponse(-1, utf8output: false, output: "", errorOutput: ""); } TextWriter output = new StringWriter(CultureInfo.InvariantCulture); bool utf8output; int returnCode = BasicCompile( _responseFileDirectory, currentDirectory, libDirectory, tempPath, commandLineArguments, output, cancellationToken, out utf8output); return new CompletedBuildResponse(returnCode, utf8output, output.ToString(), ""); }