/// <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 #2
0
        /// <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);
            }
        }