Skip to content
This repository was archived by the owner on Dec 18, 2018. It is now read-only.
This repository was archived by the owner on Dec 18, 2018. It is now read-only.

"EPIPE broken pipe" and "ECANCELED operation canceled" on event stream requests (+ ObjectDisposedException with HTTPS) #1103

@SteveSandersonMS

Description

@SteveSandersonMS

Is there a correct, supported way to implement long-running requests that are intended to be closed by the client, e.g., for EventStream?

See the (possibly naive) implementation of ServerSentEventController below. This produces a text/event-stream response. The client-side code keeps open a request to this until the user navigates away, which aborts the request.

Issue 1: Client-initiated aborts

Expected: When the client aborts the request, the HttpContext.RequestAborted token should fire immediately, and the response closes gracefully.

Actual: When the client aborts the request, HttpContext.RequestAborted does not fire immediately. After 5-10 seconds, in the console I get an error like Connection id "0HKUROLPTMNFF" communication error Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvException: Error -32 EPIPE broken pipe on OS X, with no stack trace. On Windows, the error is ECANCELED operation canceled, again with no stack trace. Immediately after this error, HttpContext.RequestAborted does fire.

Note that the errors show up regardless of whether the cancellation token is passed to WriteAsync or not.

Issue 2: Server-initiated aborts

If, while the request is ongoing, you ctrl+c in the console to terminate the server app, I'd expect it really to terminate (closing the TCP connection to the client at once). However, the app keeps running for another 5-10 seconds, sending more messages to the client during that period.

Appendix: ServerSentEventController

    public class ServerSentEventController : Controller
    {
        [Route("/event-stream")]
        public async Task MyEventStream()
        {
            HttpContext.Response.Headers.Add("Content-Type", "text/event-stream");

            var ct = HttpContext.RequestAborted;
            while (!ct.IsCancellationRequested)
            {
                try
                {
                    await HttpContext.Response.WriteAsync($"data: Hello ({DateTime.Now})\r\r", ct);
                    await Task.Delay(1000, ct);
                }
                catch (TaskCanceledException)
                {
                    // If the client aborted the request, don't regard it as an error
                }
            }
        }
    }

BTW I know there have been other issues reported previously about EPIPE broken pipe (OS X) and ECANCELED operation canceled (Windows), but those are closed and the above is still a simple repro.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions