示例#1
0
        /// <summary>
        /// Try to process the request using the server. Returns a null-containing Task if a response
        /// from the server cannot be retrieved.
        /// </summary>
        private static async Task <ServerResponse> TryProcessRequest(
            Client client,
            ServerRequest request,
            CancellationToken cancellationToken)
        {
            ServerResponse response;

            using (client)
            {
                // Write the request
                try
                {
                    ServerLogger.Log("Begin writing request");
                    await request.WriteAsync(client.Stream, cancellationToken).ConfigureAwait(false);

                    ServerLogger.Log("End writing request");
                }
                catch (Exception e)
                {
                    ServerLogger.LogException(e, "Error writing build request.");
                    return(new RejectedServerResponse());
                }

                // Wait for the compilation and a monitor to detect if the server disconnects
                var serverCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);

                ServerLogger.Log("Begin reading response");

                var responseTask = ServerResponse.ReadAsync(client.Stream, serverCts.Token);
                var monitorTask  = client.WaitForDisconnectAsync(serverCts.Token);
                await Task.WhenAny(new[] { responseTask, monitorTask }).ConfigureAwait(false);

                ServerLogger.Log("End reading response");

                if (responseTask.IsCompleted)
                {
                    // await the task to log any exceptions
                    try
                    {
                        response = await responseTask.ConfigureAwait(false);
                    }
                    catch (Exception e)
                    {
                        ServerLogger.LogException(e, "Error reading response");
                        response = new RejectedServerResponse();
                    }
                }
                else
                {
                    ServerLogger.Log("Server disconnect");
                    response = new RejectedServerResponse();
                }

                // Cancel whatever task is still around
                serverCts.Cancel();
                Debug.Assert(response != null);
                return(response);
            }
        }
示例#2
0
        internal static async Task <ServerResponse> Send(string pipeName, ServerRequest request)
        {
            using (var client = await Client.ConnectAsync(pipeName, timeout: null, cancellationToken: default).ConfigureAwait(false))
            {
                await request.WriteAsync(client.Stream).ConfigureAwait(false);

                return(await ServerResponse.ReadAsync(client.Stream).ConfigureAwait(false));
            }
        }
示例#3
0
        protected async override Task <int> ExecuteCoreAsync()
        {
            if (!IsServerRunning())
            {
                // server isn't running right now
                Out.Write("Server is not running.");
                return(0);
            }

            try
            {
                using (var client = await Client.ConnectAsync(Pipe.Value(), timeout: TimeSpan.FromSeconds(5), cancellationToken: Cancelled))
                {
                    if (client == null)
                    {
                        throw new InvalidOperationException("Couldn't connect to the server.");
                    }

                    var request = ServerRequest.CreateShutdown();
                    await request.WriteAsync(client.Stream, Cancelled).ConfigureAwait(false);

                    var response = ((ShutdownServerResponse)await ServerResponse.ReadAsync(client.Stream, Cancelled));

                    if (Wait.HasValue())
                    {
                        try
                        {
                            var process = Process.GetProcessById(response.ServerProcessId);
                            process.WaitForExit();
                        }
                        catch (Exception ex)
                        {
                            // 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 succeeded.
                            Error.Write(ex);
                        }

                        Out.Write("Server pid:{0} shut down completed.", response.ServerProcessId);
                    }
                }
            }
            catch (Exception ex) when(IsServerRunning())
            {
                // Ignore an exception that occurred while the server was shutting down.
                Error.Write(ex);
            }

            return(0);
        }
示例#4
0
        public async Task ServerResponse_WriteRead_RoundtripsProperly()
        {
            // Arrange
            var response     = new CompletedServerResponse(42, utf8output: false, output: "a string", error: "an error");
            var memoryStream = new MemoryStream();

            // Act
            await response.WriteAsync(memoryStream, CancellationToken.None);

            // Assert
            Assert.True(memoryStream.Position > 0);
            memoryStream.Position = 0;
            var result = (CompletedServerResponse)await ServerResponse.ReadAsync(memoryStream, CancellationToken.None);

            Assert.Equal(42, result.ReturnCode);
            Assert.False(result.Utf8Output);
            Assert.Equal("a string", result.Output);
            Assert.Equal("an error", result.ErrorOutput);
        }
示例#5
0
        public async Task ShutdownResponse_WriteRead_RoundtripsProperly()
        {
            // Arrange & Act 1
            var memoryStream = new MemoryStream();
            var response     = new ShutdownServerResponse(42);

            // Assert 1
            Assert.Equal(ServerResponse.ResponseType.Shutdown, response.Type);

            // Act 2
            await response.WriteAsync(memoryStream, CancellationToken.None);

            // Assert 2
            memoryStream.Position = 0;
            var read = await ServerResponse.ReadAsync(memoryStream, CancellationToken.None);

            Assert.Equal(ServerResponse.ResponseType.Shutdown, read.Type);
            var typed = (ShutdownServerResponse)read;

            Assert.Equal(42, typed.ServerProcessId);
        }
        public async Task AcceptConnection_ShutdownRequest_ReturnsShutdownResponse()
        {
            // Arrange
            var stream = new TestableStream();
            await ServerRequest.CreateShutdown().WriteAsync(stream.ReadStream, CancellationToken.None);

            stream.ReadStream.Position = 0;

            var connection     = CreateConnection(stream);
            var connectionHost = CreateConnectionHost();
            var compilerHost   = CreateCompilerHost();
            var dispatcher     = new DefaultRequestDispatcher(connectionHost, compilerHost, CancellationToken.None);

            // Act
            var connectionResult = await dispatcher.AcceptConnection(
                Task.FromResult <Connection>(connection), accept : true, cancellationToken : CancellationToken.None);

            // Assert
            Assert.Equal(ConnectionResult.Reason.ClientShutdownRequest, connectionResult.CloseReason);
            stream.WriteStream.Position = 0;
            var response = await ServerResponse.ReadAsync(stream.WriteStream).ConfigureAwait(false);

            Assert.Equal(ServerResponse.ResponseType.Shutdown, response.Type);
        }
        public async Task AcceptConnection_AcceptFalse_RejectsBuildRequest()
        {
            // Arrange
            var stream = new TestableStream();
            await EmptyServerRequest.WriteAsync(stream.ReadStream, CancellationToken.None);

            stream.ReadStream.Position = 0;

            var connection     = CreateConnection(stream);
            var connectionHost = CreateConnectionHost();
            var compilerHost   = CreateCompilerHost();
            var dispatcher     = new DefaultRequestDispatcher(connectionHost, compilerHost, CancellationToken.None);

            // Act
            var connectionResult = await dispatcher.AcceptConnection(
                Task.FromResult <Connection>(connection), accept : false, cancellationToken : CancellationToken.None);

            // Assert
            Assert.Equal(ConnectionResult.Reason.CompilationNotStarted, connectionResult.CloseReason);
            stream.WriteStream.Position = 0;
            var response = await ServerResponse.ReadAsync(stream.WriteStream).ConfigureAwait(false);

            Assert.Equal(ServerResponse.ResponseType.Rejected, response.Type);
        }
示例#8
0
        public async Task ServerRunning_CancelCompilation_CancelsSuccessfully()
        {
            // Arrange
            const int requestCount     = 5;
            var       count            = 0;
            var       completionSource = new TaskCompletionSource <bool>();
            var       host             = CreateCompilerHost(c => c.ExecuteFunc = (req, ct) =>
            {
                if (Interlocked.Increment(ref count) == requestCount)
                {
                    completionSource.SetResult(true);
                }

                ct.WaitHandle.WaitOne();
                return(new RejectedServerResponse());
            });

            var semaphore = new SemaphoreSlim(1);
            Action <object, EventArgs> onListening = (s, e) =>
            {
                semaphore.Release();
            };

            using (var serverData = ServerUtilities.CreateServer(compilerHost: host, onListening: onListening))
            {
                // Send all the requests.
                var clients = new List <Client>();
                for (var i = 0; i < requestCount; i++)
                {
                    // Wait for the server to start listening.
                    await semaphore.WaitAsync(TimeSpan.FromMinutes(1));

                    var client = await Client.ConnectAsync(serverData.PipeName, timeout : null, cancellationToken : default);

                    await EmptyServerRequest.WriteAsync(client.Stream);

                    clients.Add(client);
                }

                // Act
                // Wait until all of the connections are being processed by the server.
                await completionSource.Task;

                // Now cancel
                var stats = await serverData.CancelAndCompleteAsync();

                // Assert
                Assert.Equal(requestCount, stats.Connections);
                Assert.Equal(requestCount, count);

                // Read the server response to each client.
                foreach (var client in clients)
                {
                    var task = ServerResponse.ReadAsync(client.Stream);
                    // We expect this to throw because the stream is already closed.
                    await Assert.ThrowsAnyAsync <IOException>(() => task);

                    client.Dispose();
                }
            }
        }