diff --git a/src/platform_impl/linux/wayland/event_loop/mod.rs b/src/platform_impl/linux/wayland/event_loop/mod.rs
index afe7c3e5..2a00afa6 100644
--- a/src/platform_impl/linux/wayland/event_loop/mod.rs
+++ b/src/platform_impl/linux/wayland/event_loop/mod.rs
@@ -16,13 +16,13 @@ use sctk::reexports::client::globals;
 use sctk::reexports::client::{Connection, Proxy, QueueHandle, WaylandSource};
 
 use crate::dpi::{LogicalSize, PhysicalSize};
-use crate::error::RunLoopError;
+use crate::error::{OsError as RootOsError, RunLoopError};
 use crate::event::{Event, StartCause, WindowEvent};
 use crate::event_loop::{ControlFlow, EventLoopWindowTarget as RootEventLoopWindowTarget};
 use crate::platform::pump_events::PumpStatus;
 use crate::platform_impl::platform::min_timeout;
 use crate::platform_impl::platform::sticky_exit_callback;
-use crate::platform_impl::EventLoopWindowTarget as PlatformEventLoopWindowTarget;
+use crate::platform_impl::{EventLoopWindowTarget as PlatformEventLoopWindowTarget, OsError};
 
 mod proxy;
 pub mod sink;
@@ -153,7 +153,7 @@ impl<T: 'static> EventLoop<T> {
             return Err(RunLoopError::AlreadyRunning);
         }
 
-        loop {
+        let exit = loop {
             match self.pump_events_with_timeout(None, &mut event_handler) {
                 PumpStatus::Exit(0) => {
                     break Ok(());
@@ -165,7 +165,15 @@ impl<T: 'static> EventLoop<T> {
                     continue;
                 }
             }
-        }
+        };
+
+        // Applications aren't allowed to carry windows between separate
+        // `run_ondemand` calls but if they have only just dropped their
+        // windows we need to make sure those last requests are sent to the
+        // compositor.
+        let _ = self.roundtrip().map_err(RunLoopError::Os);
+
+        exit
     }
 
     pub fn pump_events<F>(&mut self, event_handler: F) -> PumpStatus
@@ -574,6 +582,22 @@ impl<T: 'static> EventLoop<T> {
             error.into()
         })
     }
+
+    fn roundtrip(&mut self) -> Result<usize, RootOsError> {
+        let state = match &mut self.window_target.p {
+            PlatformEventLoopWindowTarget::Wayland(window_target) => window_target.state.get_mut(),
+            #[cfg(feature = "x11")]
+            _ => unreachable!(),
+        };
+
+        let mut wayland_source = self.wayland_dispatcher.as_source_mut();
+        let event_queue = wayland_source.queue();
+        event_queue.roundtrip(state).map_err(|_| {
+            os_error!(OsError::WaylandMisc(
+                "failed to do a final roundtrip before exiting the loop."
+            ))
+        })
+    }
 }
 
 pub struct EventLoopWindowTarget<T> {
diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs
index c6381288..897fded3 100644
--- a/src/platform_impl/linux/x11/mod.rs
+++ b/src/platform_impl/linux/x11/mod.rs
@@ -62,7 +62,7 @@ use self::{
     event_processor::EventProcessor,
     ime::{Ime, ImeCreationError, ImeReceiver, ImeRequest, ImeSender},
 };
-use super::common::xkb_state::KbdState;
+use super::{common::xkb_state::KbdState, OsError};
 use crate::{
     error::{OsError as RootOsError, RunLoopError},
     event::{Event, StartCause},
@@ -440,7 +440,7 @@ impl<T: 'static> EventLoop<T> {
             return Err(RunLoopError::AlreadyRunning);
         }
 
-        loop {
+        let exit = loop {
             match self.pump_events_with_timeout(None, &mut event_handler) {
                 PumpStatus::Exit(0) => {
                     break Ok(());
@@ -452,7 +452,18 @@ impl<T: 'static> EventLoop<T> {
                     continue;
                 }
             }
-        }
+        };
+
+        // Applications aren't allowed to carry windows between separate
+        // `run_ondemand` calls but if they have only just dropped their
+        // windows we need to make sure those last requests are sent to the
+        // X Server.
+        let wt = get_xtarget(&self.target);
+        wt.x_connection().sync_with_server().map_err(|x_err| {
+            RunLoopError::Os(os_error!(OsError::XError(Arc::new(X11Error::Xlib(x_err)))))
+        })?;
+
+        exit
     }
 
     pub fn pump_events<F>(&mut self, event_handler: F) -> PumpStatus