litespeedtech / litespeedtech/lsquic

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

Open
#613 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

question
Dominant language
C
Stars
1.9k
Forks
397
Avg merge
2d 22h
Merged PRs (30d)
8

Description

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!

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the ea_packets_out callback and the engine's handling of its return value, then inspect how partial UDP sends and EAGAIN are treated. Compare that behavior with the multiple-socket setup described in the issue and the epoll/kqueue retry path. Done means the recommended return and buffering behavior for packets targeting other sockets is established.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
networking
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.