Skip to content

Add EventLoopIteration to Connection methods: send_on_path, recv and on_timeout#2410

Draft
antoniovicente wants to merge 4 commits into
masterfrom
antonio/event_loop_iter
Draft

Add EventLoopIteration to Connection methods: send_on_path, recv and on_timeout#2410
antoniovicente wants to merge 4 commits into
masterfrom
antonio/event_loop_iter

Conversation

@antoniovicente
Copy link
Copy Markdown
Contributor

This refactor is in preparation for #2328

This change simplifies the event loop and removes the need to bias the
select! to avoid starvation by serializing all the event loop actions
and clarifying the start and end of the work loop iteration.
@antoniovicente antoniovicente force-pushed the antonio/event_loop_iter branch 4 times, most recently from c0a7b0f to 0898578 Compare March 20, 2026 22:00
@antoniovicente antoniovicente force-pushed the antonio/event_loop_iter branch from 0898578 to 19a80e0 Compare March 20, 2026 22:15
Comment thread quiche/src/ffi.rs
}
}

#[no_mangle]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

general comment: this seems like a sizeable amount of code to add to the FFI and it doesn't update the C examples to call it. I'd suggest punting on C entirely for now

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that the right thing would be to update examples to use the new API and fully delete the old API in a future PR.

Comment thread quiche/src/lib.rs Outdated
/// [`on_timeout`]: Connection::on_timeout
pub struct EventLoopIteration {
/// The time at which this event loop iteration started.
now: Instant,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: if the field represents the start, just call it that

Suggested change
now: Instant,
start: Instant,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent suggestion. ty.

Comment thread quiche/src/lib.rs Outdated
Comment thread quiche/src/lib.rs
/// ```
pub fn recv(&mut self, buf: &mut [u8], info: RecvInfo) -> Result<usize> {
pub fn recv(
&mut self, iteration: &EventLoopIteration, buf: &mut [u8], info: RecvInfo,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the changes to extant methods are too disruptive TBH, as it pushes work on all downstreams and risks them making the wrong decision. If its safe to call them with a new EventLoopIteration each time, that should just be the default internal behaviour.

IOW like with the FFI proposal, I'd suggest adding variants that have a suffix of with_iteration, _with_ev_loop, or something. Then the old methods can just construct a EventLoopIteration to pass onto the new ones

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not correct to pass a new EventLoopIteration each time. Currently it mostly works, but #2328 require this information and it does need to be correct.

Creating a new EventLoopIteration each time will result in BBR not working correctly; app-limited will be computed incorrectly some of the time.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right but requiring all apps to make a change for a congestion control algo they might not be interested in seems pretty extreme.

As this PR highlights, we have dozens of tests that do not care about the app-limited behaviour one way or another

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the solution is to have different API requirements for BBR and not, I think we could do that. But I'ld like us to make a decision.

We could do something to require that the hook introduced in #2328 be called if the code wants to use BBR, or we could try forcing a wider API change to force users of quiche to reconsider the correctness of their integrations.

Ideally we'ld have a simpler API to the event loop which provides hooks to consume read packets, emit packets and handling of timeouts using a single call, instead of the current API which forces the app to do timeout handling, recv and send in the right order.

Comment thread tokio-quiche/src/quic/io/worker.rs Outdated
) -> QuicResult<()> {
std::future::poll_fn(|_| {
match self.gather_data_from_quiche_conn(qconn, buffer) {
match self.gather_data_from_quiche_conn(iteration, qconn, buffer) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: We may need a new iteration on every poll so we can have a fresh now

Comment thread quiche/src/ffi.rs
}
}

#[no_mangle]
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that the right thing would be to update examples to use the new API and fully delete the old API in a future PR.

Comment thread quiche/src/lib.rs
/// ```
pub fn recv(&mut self, buf: &mut [u8], info: RecvInfo) -> Result<usize> {
pub fn recv(
&mut self, iteration: &EventLoopIteration, buf: &mut [u8], info: RecvInfo,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not correct to pass a new EventLoopIteration each time. Currently it mostly works, but #2328 require this information and it does need to be correct.

Creating a new EventLoopIteration each time will result in BBR not working correctly; app-limited will be computed incorrectly some of the time.

Comment thread quiche/src/lib.rs Outdated
/// [`on_timeout`]: Connection::on_timeout
pub struct EventLoopIteration {
/// The time at which this event loop iteration started.
now: Instant,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent suggestion. ty.


loop {
let now = Instant::now();
let iteration = EventLoopIteration::new();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm struggling to follow this change a bit since I'm less familiar with TQ guts. It would seem that if ever we broke the loop at https://github.com/cloudflare/quiche/pull/2410/changes#diff-77397d0e30b86551f31a2fc4fc5e2adc5fb62fd3091c5e8a35b950bd43fc7c1cR345, then the quiche timeout wouldn't be called. Is that ok?

@antoniovicente antoniovicente self-assigned this Apr 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants