From 6105641daf5bcba87b783b93273d850ac9c96d55 Mon Sep 17 00:00:00 2001 From: anh nguyen <29374105+areporeporepo@users.noreply.github.com> Date: Wed, 25 Mar 2026 11:13:57 -0700 Subject: [PATCH 1/2] fix(net): break tx loop on non-recoverable errors to prevent busy-loop When process_tx() returns a persistent error other than NothingWritten (e.g. Internal or ProcessNotRunning), the loop in process_tx_loop() continues spinning if the guest keeps supplying TX buffers, because tx_has_deferred_frame is false and has_new_entries is true. Break immediately on non-recoverable errors instead of returning false. The worker will be re-entered on the next TX queue kick or backend socket writable event from epoll. Fixes: containers/libkrun#602 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: anh nguyen Signed-off-by: anh nguyen <29374105+areporeporepo@users.noreply.github.com> --- src/devices/src/virtio/net/worker.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/devices/src/virtio/net/worker.rs b/src/devices/src/virtio/net/worker.rs index 133e23b46..8a1fc0d4a 100644 --- a/src/devices/src/virtio/net/worker.rs +++ b/src/devices/src/virtio/net/worker.rs @@ -284,7 +284,11 @@ impl NetWorker { Err(TxError::Backend(WriteError::NothingWritten)) => true, Err(e) => { log::error!("Failed to process tx: {e:?}"); - false + // Break immediately on non-recoverable errors to avoid a + // busy-loop when the guest keeps supplying TX buffers. + // The worker will be re-entered on the next TX queue kick + // or backend-writable event. + break; } _ => false, }; From 8e9d85db82c131dfb1dc1f39af9c12ebb07e5be0 Mon Sep 17 00:00:00 2001 From: anh nguyen <29374105+areporeporepo@users.noreply.github.com> Date: Sun, 5 Apr 2026 12:07:44 -0700 Subject: [PATCH 2/2] fix(net): re-enable notifications before breaking tx loop Address review feedback: the v1 break skipped enable_notification(), which could cause the guest to stop sending TX queue kicks (especially with EVENT_IDX where enable_notification writes avail_event). Also explicitly reset tx_has_deferred_frame to false for clarity. Fixes: containers/libkrun#602 Signed-off-by: anh nguyen <29374105+areporeporepo@users.noreply.github.com> --- src/devices/src/virtio/net/worker.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/devices/src/virtio/net/worker.rs b/src/devices/src/virtio/net/worker.rs index 8a1fc0d4a..111d2145a 100644 --- a/src/devices/src/virtio/net/worker.rs +++ b/src/devices/src/virtio/net/worker.rs @@ -284,10 +284,10 @@ impl NetWorker { Err(TxError::Backend(WriteError::NothingWritten)) => true, Err(e) => { log::error!("Failed to process tx: {e:?}"); - // Break immediately on non-recoverable errors to avoid a - // busy-loop when the guest keeps supplying TX buffers. - // The worker will be re-entered on the next TX queue kick - // or backend-writable event. + // Re-enable notifications before breaking so the guest + // can still kick the TX queue on future descriptors. + let _ = self.tx_q.queue.enable_notification(&self.mem); + self.tx_has_deferred_frame = false; break; } _ => false,