Beispiel #1
0
        public async Task NoCompilationsProcessShutdown()
        {
            var host = new TestableCompilerServerHost(runCompilation: delegate
            {
                // We should never get here.
                Assert.False(true);
                throw null;
            });

            var(clientStream, serverStream) = await CreateNamedPipePair().ConfigureAwait(false);

            try
            {
                var connection = new NamedPipeClientConnection(host, "identifier", serverStream);
                await BuildRequest.CreateShutdown().WriteAsync(clientStream).ConfigureAwait(false);

                var connectionData = await connection.HandleConnection(allowCompilationRequests : false).ConfigureAwait(false);

                Assert.Equal(CompletionReason.ClientShutdownRequest, connectionData.CompletionReason);
                Assert.Null(connectionData.KeepAlive);

                var response = await BuildResponse.ReadAsync(clientStream);

                Assert.Equal(BuildResponse.ResponseType.Shutdown, response.Type);
            }
            finally
            {
                clientStream.Close();
                serverStream.Close();
            }
        }
        public async Task ShutdownRequest(bool allowCompilationRequests)
        {
            var hitCompilation     = false;
            var compilerServerHost = new TestableCompilerServerHost(delegate
            {
                hitCompilation = true;
                throw new Exception("");
            });

            BuildResponse?response = null;
            var           clientConnectionHandler = new ClientConnectionHandler(compilerServerHost);
            var           clientConnection        = new TestableClientConnection()
            {
                ReadBuildRequestFunc   = _ => Task.FromResult(BuildRequest.CreateShutdown()),
                WriteBuildResponseFunc = (r, _) =>
                {
                    response = r;
                    return(Task.CompletedTask);
                }
            };

            var completionData = await clientConnectionHandler.ProcessAsync(
                Task.FromResult <IClientConnection>(clientConnection),
                allowCompilationRequests : allowCompilationRequests).ConfigureAwait(false);

            Assert.False(hitCompilation);
            Assert.Equal(new CompletionData(CompletionReason.RequestCompleted, shutdownRequested: true), completionData);
            Assert.True(response is ShutdownBuildResponse);
        }
Beispiel #3
0
        internal async Task <int> SendShutdownAsync(CancellationToken cancellationToken = default)
        {
            var response = await SendAsync(BuildRequest.CreateShutdown(), cancellationToken)
                           .ConfigureAwait(false);

            return(((ShutdownBuildResponse)response).ServerProcessId);
        }
Beispiel #4
0
        public void MutexAcquiredWhenRunningServer()
        {
            var  pipeName           = Guid.NewGuid().ToString("N");
            var  mutexName          = BuildServerConnection.GetServerMutexName(pipeName);
            var  host               = new TestableClientConnectionHost();
            bool?wasServerMutexOpen = null;

            host.Add(
                () =>
            {
                // Use a thread instead of Task to guarantee this code runs on a different
                // thread and we can validate the mutex state.
                var tcs    = new TaskCompletionSource <IClientConnection>();
                var thread = new Thread(
                    _ =>
                {
                    wasServerMutexOpen = BuildServerConnection.WasServerMutexOpen(
                        mutexName
                        );

                    var client = new TestableClientConnection()
                    {
                        ReadBuildRequestFunc = _ =>
                                               Task.FromResult(ProtocolUtil.EmptyCSharpBuildRequest),
                        WriteBuildResponseFunc = (r, _) => Task.CompletedTask,
                    };
                    tcs.SetResult(client);
                }
                    );

                thread.Start();
                return(tcs.Task);
            }
                );

            host.Add(
                () =>
            {
                var client = new TestableClientConnection()
                {
                    ReadBuildRequestFunc   = _ => Task.FromResult(BuildRequest.CreateShutdown()),
                    WriteBuildResponseFunc = (r, _) => Task.CompletedTask,
                };
                return(Task.FromResult <IClientConnection>(client));
            }
                );

            var result = BuildServerController.CreateAndRunServer(
                pipeName,
                clientConnectionHost: host,
                keepAlive: TimeSpan.FromMilliseconds(-1)
                );

            Assert.Equal(CommonCompiler.Succeeded, result);
            Assert.True(wasServerMutexOpen);
        }
Beispiel #5
0
        public async Task ShutdownRequestWriteRead()
        {
            var memoryStream = new MemoryStream();
            var request      = BuildRequest.CreateShutdown();
            await request.WriteAsync(memoryStream, CancellationToken.None);

            memoryStream.Position = 0;
            var read = await BuildRequest.ReadAsync(memoryStream, CancellationToken.None);

            VerifyShutdownRequest(read);
        }
        /// <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(CancellationToken))
        {
            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))
                {
                    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);
            }
        }
Beispiel #7
0
        public void ShutdownMessage()
        {
            var request = BuildRequest.CreateShutdown();

            VerifyShutdownRequest(request);
            Assert.Equal(1, request.Arguments.Count);

            var argument = request.Arguments[0];

            Assert.Equal(BuildProtocolConstants.ArgumentId.Shutdown, argument.ArgumentId);
            Assert.Equal(0, argument.ArgumentIndex);
            Assert.Equal("", argument.Value);
        }
Beispiel #8
0
        public async Task NoCompilationsProcessShutdown()
        {
            var stream = new TestableStream();
            await BuildRequest.CreateShutdown().WriteAsync(stream.ReadStream, CancellationToken.None).ConfigureAwait(true);

            stream.ReadStream.Position = 0;

            var connection     = CreateConnection(stream);
            var connectionData = await connection.HandleConnection(allowCompilationRequests : false).ConfigureAwait(false);

            Assert.Equal(CompletionReason.ClientShutdownRequest, connectionData.CompletionReason);

            stream.WriteStream.Position = 0;
            var response = await BuildResponse.ReadAsync(stream.WriteStream).ConfigureAwait(false);

            Assert.Equal(BuildResponse.ResponseType.Shutdown, response.Type);
        }
Beispiel #9
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: null, cancellationToken: Cancelled))
                {
                    var request = BuildRequest.CreateShutdown();
                    await request.WriteAsync(client.Stream, Cancelled).ConfigureAwait(false);

                    var response = ((ShutdownBuildResponse)await BuildResponse.ReadAsync(client.Stream, Cancelled));

                    if (Wait.HasValue())
                    {
                        try
                        {
                            var process = Process.GetProcessById(response.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.
                        }

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

            return(0);
        }
Beispiel #10
0
        internal static async Task <int> SendShutdown(string pipeName)
        {
            var response = await Send(pipeName, BuildRequest.CreateShutdown());

            return(((ShutdownBuildResponse)response).ServerProcessId);
        }