Esempio n. 1
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 <bool> RunServerShutdownRequestAsync(
            string pipeName,
            int?timeoutOverride,
            bool waitForProcess,
            ICompilerServerLogger logger,
            CancellationToken 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(true);
            }

            try
            {
                var request = BuildRequest.CreateShutdown();

                // Don't create the server when sending a shutdown request. That would defeat the
                // purpose a bit.
                var response = await RunServerBuildRequestAsync(
                    request,
                    pipeName,
                    timeoutOverride,
                    tryCreateServerFunc : (_, _) => false,
                    logger,
                    cancellationToken).ConfigureAwait(false);

                if (response is ShutdownBuildResponse shutdownBuildResponse)
                {
                    if (waitForProcess)
                    {
                        try
                        {
                            var process = Process.GetProcessById(shutdownBuildResponse.ServerProcessId);
#if NET5_0_OR_GREATER
                            await process.WaitForExitAsync(cancellationToken).ConfigureAwait(false);
#else
                            process.WaitForExit();
#endif
                        }
                        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(true);
                }

                return(wasServerRunning(pipeName) == false);
            }
            catch (Exception)
            {
                // 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(wasServerRunning(pipeName) == false);
            }