Skip to content

QuicListener.AcceptConnectionAsync rethrowing exceptions #75115

Closed

Description

@JamesNK

QuicListener.AcceptConnectionAsync throws in the following scenarios (that I know of):

  1. QuicException with QuicError.OperationAborted. Happens when the listener is disposed while waiting for a connection.
  2. ObjectDisposedException. Happens when AcceptConnectionAsync is called after disposing the listener.
  3. AuthenticationException. Happens when the client and server fail to negotiate a connection, e.g. server has an invalid certificate and the client rejects it.
  4. ArgumentException. Happens when the options returned from the callback are invalid. e.g. a server certificate isn't configured in the callback.
  5. Any exception is thrown in the callback. Happens when an exception is thrown in the callback and is then rethrown from AcceptConnectionAsync.

I think 5 is very broad. There should be a way to disambiguate a rethrown exception from important exceptions that are used to signal the health of the listener. e.g. someone could accidentally throw an ODE in the callback, which the code that calls the listener interprets as the listener is shut down and to stop listening for connections.

I think the exception from 5, and maybe also 3 and 4, should be wrapped in another exception that says an attempt to accept a connection failed. The inner exception then provides more detail.

Activity

  1. ghost added
    untriagedNew issue has not been triaged by the area owner
    on Sep 6, 2022
  2. karelz commented on Sep 6, 2022

    @karelz
    Member

    Split from discussion: dotnet/aspnetcore#43730 (comment)

    It sounds reasonable to me. @ManickaP @rzikm @CarnaViire @wfurt any thoughts?
    If we agree, we should try to do it in 7.0 to prevent breaking changes in 8.0 ... even though QUIC APIs are preview, so we will be allowed to make them.

  3. JamesNK commented on Sep 6, 2022

    @JamesNK
    MemberAuthor

    Currently, aspnetcore has to assume any exception thrown from AcceptConnectionAsync can be retried, unless it is OperationAborted or ODE.

    while (true)
    {
        try
        {
            var connection = await _listener.AcceptConnectionAsync();
            return connection;
        }
        catch (ObjectDisposedException)
        {
            return null;
        }
        catch (QuicException ex) when (ex.QuicError == QuicError.OperationAborted)
        {
            return null;
        }
        catch (Exception)
        {
            // retry
        }
    }

    This feels a little dangerous. What happens if a bug causes AcceptConnectionAsync to break and throw for another reason? We'd be stuck in this loop, throwing errors, catching errors, and burning CPU.

    It would be nice if there was a known exception type (or QuicError type) for failed accepting of connections to check for. Unexpected exceptions could then be logged and exit this loop.

  4. karelz commented on Sep 6, 2022

    @karelz
    Member

    Triage: We should look at how we deal with these things in HttpClient and SslStream callbacks.

    • HttpClient wraps it with HttpRequestException (per @MihaZupan).

    Note: We might still decide to wrap exceptions in QUIC APIs.

  5. added this to the 7.0.0 milestone on Sep 6, 2022
  6. ghost removed
    untriagedNew issue has not been triaged by the area owner
    on Sep 6, 2022
  7. karelz commented on Sep 7, 2022

    @karelz
    Member

    Duplicate of #75184

  8. 2 remaining items

  9. assigned and unassigned on Jun 8, 2023
  10. reopened this on Jun 23, 2023
  11. modified the milestones: 7.0.0, 8.0.0 on Jun 23, 2023
  12. karelz commented on Jul 18, 2023

    @karelz
    Member

    @wfurt why did you reopen it?
    @ManickaP thinks it should be closed with your last 2 PRs merged yesterday.

  13. wfurt commented on Jul 18, 2023

    @wfurt
    Member

    mostly. We still should look at 1. IMHO e.g. Disposing listener should throw ODE. The changes addressed $5 e.g. we wrap callback exceptions now.

  14. ManickaP commented on Jul 18, 2023

    @ManickaP
    Member

    It's a one-liner in here https://source.dot.net/#System.Net.Quic/System/Net/Quic/QuicListener.cs,376
    And the same thing applies to QuicConnection and AcceptStream: https://source.dot.net/#System.Net.Quic/System/Net/Quic/QuicConnection.cs,645
    ==> 2 liner change

  15. assigned and unassigned on Jul 18, 2023
  16. wfurt commented on Jul 19, 2023

    @wfurt
    Member

    do you want to do it and write test @ManickaP? I will not get to it this week.

  17. ManickaP commented on Jul 20, 2023

    @ManickaP
    Member

    Yep, that's why I assigned myself. I already have something in progress.

  18. modified the milestones: 8.0.0, 9.0.0 on Aug 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions