Beispiel #1
0
    // The message pump.
    // When we start listening for the next request on one thread, we may need to be sure that the
    // completion continues on another thread as to not block the current request processing.
    // The awaits will manage stack depth for us.
    private async Task ProcessRequestsWorker()
    {
        Debug.Assert(RequestContextFactory != null);

        // Allocate and accept context per loop and reuse it for all accepts
        using var acceptContext = new AsyncAcceptContext(Listener, RequestContextFactory);

        int workerIndex = Interlocked.Increment(ref _acceptorCounts);

        while (!Stopping && workerIndex <= _maxAccepts)
        {
            // Receive a request
            RequestContext requestContext;
            try
            {
                requestContext = await Listener.AcceptAsync(acceptContext);

                if (!Listener.ValidateRequest(requestContext))
                {
                    // Dispose the request
                    requestContext.ReleasePins();
                    requestContext.Dispose();

                    // If either of these is false then a response has already been sent to the client, so we can accept the next request
                    continue;
                }
            }
            catch (Exception exception)
            {
                Debug.Assert(Stopping);
                if (Stopping)
                {
                    Log.AcceptErrorStopping(_logger, exception);
                }
                else
                {
                    Log.AcceptError(_logger, exception);
                }
                continue;
            }
            try
            {
                if (_options.UnsafePreferInlineScheduling)
                {
                    await requestContext.ExecuteAsync();
                }
                else
                {
                    ThreadPool.UnsafeQueueUserWorkItem(requestContext, preferLocal: false);
                }
            }
            catch (Exception ex)
            {
                // Request processing failed
                // Log the error message, release throttle and move on
                Log.RequestListenerProcessError(_logger, ex);
            }
        }
        Interlocked.Decrement(ref _acceptorCounts);
    }
Beispiel #2
0
    /// <summary>
    /// Accept a request from the incoming request queue.
    /// </summary>
    internal ValueTask <RequestContext> AcceptAsync(AsyncAcceptContext acceptContext)
    {
        CheckDisposed();
        Debug.Assert(_state != State.Stopped, "Listener has been stopped.");

        return(acceptContext.AcceptAsync());
    }
Beispiel #3
0
        /// <summary>
        /// AcceptAsync extension with timeout. This extension should be used in all tests to prevent
        /// unexpected hangs when a request does not arrive.
        /// </summary>
        internal static async Task <RequestContext> AcceptAsync(this HttpSysListener server, TimeSpan timeout)
        {
            var factory = new TestRequestContextFactory(server);

            using var acceptContext = new AsyncAcceptContext(server, factory);

            async Task <RequestContext> AcceptAsync()
            {
                while (true)
                {
                    var requestContext = await server.AcceptAsync(acceptContext);

                    if (server.ValidateRequest(requestContext))
                    {
                        requestContext.InitializeFeatures();
                        return(requestContext);
                    }
                }
            }

            var acceptTask    = AcceptAsync();
            var completedTask = await Task.WhenAny(acceptTask, Task.Delay(timeout));

            if (completedTask == acceptTask)
            {
                return(await acceptTask);
            }
            else
            {
                server.Dispose();
                throw new TimeoutException("AcceptAsync has timed out.");
            }
        }
Beispiel #4
0
        /// <summary>
        /// AcceptAsync extension with timeout. This extension should be used in all tests to prevent
        /// unexpected hangs when a request does not arrive.
        /// </summary>
        internal static async Task <RequestContext> AcceptAsync(this HttpSysListener server, TimeSpan timeout)
        {
            var acceptContext = new AsyncAcceptContext(server);
            var acceptTask    = server.AcceptAsync(acceptContext).AsTask();
            var completedTask = await Task.WhenAny(acceptTask, Task.Delay(timeout));

            if (completedTask == acceptTask)
            {
                return(await acceptTask);
            }
            else
            {
                server.Dispose();
                throw new TimeoutException("AcceptAsync has timed out.");
            }
        }