aboutsummaryrefslogtreecommitdiff
path: root/src/server/headless.rs
diff options
context:
space:
mode:
authorEric Yue <jiacheng.yue@foxmail.com>2026-09-28 04:16:55 +0800
committerGitHub <noreply@github.com>2026-09-27 22:16:55 +0200
commitc210c953e454882c5ef3cd366bcd4b53b7c64791 (patch)
tree785c9325e0ac9ce3d647aa5dd17e063df38dd3e5 /src/server/headless.rs
parent87c08c6b7a1dbd250fa3a8e9424a47b3176f99eb (diff)
fix: bound external event batches in the server loop (#4671)
Diffstat (limited to 'src/server/headless.rs')
-rw-r--r--src/server/headless.rs15
1 files changed, 13 insertions, 2 deletions
diff --git a/src/server/headless.rs b/src/server/headless.rs
index fe8a67e8..da3baf30 100644
--- a/src/server/headless.rs
+++ b/src/server/headless.rs
@@ -82,6 +82,11 @@ mod render;
mod retained_surface;
mod surface_interest;
+// Producers can refill even a bounded channel while it is being drained.
+// Yield to scheduled work and rendering between batches; select! below
+// immediately wakes for any messages left in either external queue.
+const EXTERNAL_EVENT_DRAIN_LIMIT: usize = 64;
+
pub use bootstrap::run_server;
use lifecycle::wait_for_live_handoff_response_write;
#[cfg(unix)]
@@ -1011,7 +1016,10 @@ impl HeadlessServer {
/// Drains server events from the dedicated channel.
fn drain_server_events(&mut self) -> bool {
let mut changed = false;
- while !self.should_quit.load(Ordering::Acquire) {
+ for _ in 0..EXTERNAL_EVENT_DRAIN_LIMIT {
+ if self.should_quit.load(Ordering::Acquire) {
+ break;
+ }
let Ok(ev) = self.server_event_rx.try_recv() else {
break;
};
@@ -2788,7 +2796,10 @@ impl HeadlessServer {
/// During shutdown, remaining requests get a `server_unavailable` error.
fn drain_api_requests_with_shutdown_check(&mut self) -> bool {
let mut changed = false;
- while !self.should_quit.load(Ordering::Acquire) {
+ for _ in 0..EXTERNAL_EVENT_DRAIN_LIMIT {
+ if self.should_quit.load(Ordering::Acquire) {
+ break;
+ }
let Ok(msg) = self.app.api_rx.try_recv() else {
break;
};