Skip to content

IP_RECVERR can prevent graceful connection termination #2704

Description

@stormshield-fabs

The recently added support of IP_RECVERR (#2646) has an unintended impact on the normal operation of the socket: when an error is received on the socket, the next syscall (recvmmsg or sendmsg for quinn) will ignore the data and return this error (once for each enqueued error).

This is described (although quite discreetly I think) in the recv(2) manpage:

After an error has been passed, the pending socket error is regenerated based on the next queued error and will be passed on the next socket operation.

In practice, this does not have a huge functional impact since reads and writes are retried in quinn.

However, we stumbled upon this when chasing a lost CONNECTION_CLOSE frame that should have been sent when closing the Connection. It turned out the packet containing this frame was absorbed by sendmsg, since an ICMP error had occured right before it was called. This error is only meant to be a notification that an error was enqueued and is not related to the packet we're trying to sent (the syscall returns an error even if the error was for a different remote address). Because close notifications are not retried, the remote peer never gets it.

I believe this was understood in a previous implementation, since this comment hints at a refactor from a design that pulled errors immediately to the external getter design : https://github.com/quinn-rs/quinn/pull/2421/changes#r2450585268

To move forward, we would like to suggest adding an option to let users choose if the IP_RECVERR flag is passed on the socket.

Additionally, we think both recvmmsg and sendmsg calls should be wrapped to capture such errors and emit a notification that the user could receive to know if they should call the new recv_transport_error method. Then, the syscall should be retried (and that would fix the silently dropped CONNECTION_CLOSE).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions