Skip to content

[Question] Best practices for handling partial writes (EAGAIN) in ea_packets_out with "One Engine, Multiple Sockets"? #613

@nlifew

Description

@nlifew

Hi lsquic team,

I am currently implementing a C++ networking library using lsquic. I have adopted a "One Engine Per Thread, Multiple Sockets" architecture:

Single Engine: A thread-local lsquic_engine_t.

Multiple Sockets: Each QUIC connection owns its own dedicated UDP socket (bound to a unique ephemeral port).

The Challenge:

I am facing a dilemma regarding the return value of ea_packets_out when one specific socket hits a full send buffer (EAGAIN / EWOULDBLOCK), but others are fine.

Scenario: Suppose the engine calls ea_packets_out with a batch of 25 packets:

Packets 0-19 (20 total): Destined for Socket A.

Packets 20-24 (5 total): Destined for Socket B.

During the loop, I successfully send the first 5 packets for Socket A, but then Socket A hits EAGAIN (send buffer full). Socket B is still perfectly capable of sending.

My Question: What is the appropriate return value for ea_packets_out in this case?

Return 5 (The "Honest" Approach): If I return 5, the engine assumes the remaining 20 packets failed. While this correctly stops Socket A, it also implicitly stops Socket B (Head-of-Line Blocking), preventing Socket B from sending its 5 packets even though its socket is ready.

Return 25 (The "Optimistic" Approach): If I return 25, I effectively "lie" to the engine. I would have to buffer the remaining 15 packets for Socket A in user-space (handling retries via epoll/kqueue) and proceed to send Socket B's packets immediately.

Is approach #2 (returning the full count and buffering locally) the recommended best practice for lsquic to ensure isolation between connections? Or does the engine have internal mechanisms to handle this "partial batch failure" scenario without blocking other connections?

Thank you for your time and for this amazing library!

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions