Exemple #1
0
 private Task CompileNamedTypeAsTask(NamedTypeSymbol symbol)
 {
     return(Task.Run(() =>
     {
         try
         {
             CompileNamedType(symbol);
             return (object)null;
         }
         catch (Exception e) if (CompilerFatalError.Report(e))
             {
                 throw ExceptionUtilities.Unreachable;
             }
     }, this.cancellationToken));
 }
Exemple #2
0
        /// <summary>
        /// Checks to see if memory is available, and if it is creates a new
        /// Connection object, awaits the completion of the connection, then
        /// runs <see cref="ConnectionCompleted"/> for cleanup.
        /// </summary>
        private async Task DispatchConnection(NamedPipeServerStream pipeStream)
        {
            try
            {
                // There is always a race between timeout and connections because
                // there is no way to cancel listening on the pipe without
                // closing the pipe. We immediately increment the connection
                // semaphore while processing connections in order to narrow
                // the race window as much as possible.
                Interlocked.Increment(ref this.activeConnectionCount);

                if (Environment.Is64BitProcess || MemoryHelper.IsMemoryAvailable())
                {
                    CompilerServerLogger.Log("Memory available - accepting connection");

                    Connection connection = new Connection(pipeStream, handler, this.keepAliveTimer);

                    try
                    {
                        await connection.ServeConnection().ConfigureAwait(false);
                    }
                    catch (ObjectDisposedException e)
                    {
                        // If the client closes the pipe while we're reading or writing
                        // we'll get an object disposed exception on the pipe
                        // Log the failure and continue
                        CompilerServerLogger.Log(
                            "Client pipe closed: received exception " + e.Message);
                    }
                }
                else
                {
                    CompilerServerLogger.Log("Memory tight - rejecting connection.");
                    // As long as we haven't written a response, the client has not
                    // committed to this server instance and can look elsewhere.
                    pipeStream.Close();

                    // We didn't create a connection -- decrement the semaphore
                    Interlocked.Decrement(ref this.activeConnectionCount);
                }
                ConnectionCompleted();
            }
            catch (Exception e) if (CompilerFatalError.Report(e))
                {
                    throw ExceptionUtilities.Unreachable;
                }
        }
Exemple #3
0
        /// <summary>
        /// Checks to see if memory is available, and if it is creates a new
        /// Connection object, awaits the completion of the connection, then
        /// runs <see cref="ConnectionCompleted"/> for cleanup.
        /// </summary>
        private async Task DispatchConnection(NamedPipeServerStream pipeStream)
        {
            try
            {
                // There is always a race between timeout and connections because
                // there is no way to cancel listening on the pipe without
                // closing the pipe. We immediately increment the connection
                // semaphore while processing connections in order to narrow
                // the race window as much as possible.
                Interlocked.Increment(ref this.activeConnectionCount);

                if (Environment.Is64BitProcess || MemoryHelper.IsMemoryAvailable())
                {
                    CompilerServerLogger.Log("Memory available - accepting connection");

                    Connection connection = new Connection(pipeStream, handler);

                    await connection.ServeConnection().ConfigureAwait(false);

                    // The connection should be finished
                    ConnectionCompleted(connection);
                }
                else
                {
                    CompilerServerLogger.Log("Memory tight - rejecting connection.");
                    // As long as we haven't written a response, the client has not
                    // committed to this server instance and can look elsewhere.
                    pipeStream.Close();

                    // We didn't create a connection -- decrement the semaphore
                    Interlocked.Decrement(ref this.activeConnectionCount);

                    // Start a terminate server timer if there are no active
                    // connections
                    StartTimeoutTimerIfNecessary();
                }
            }
            catch (Exception e) if (CompilerFatalError.Report(e))
                {
                    throw ExceptionUtilities.Unreachable;
                }
        }
Exemple #4
0
            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);
            }