Desktop: Make shutdown more robust and fix panic caused by invalid viewport scale (#3783)

* Fix panic caused by invalid viewport scale

* Make shutdown more robust
This commit is contained in:
Timon 2026-02-22 17:28:35 +00:00 committed by GitHub
parent 9d83998463
commit a2d3b3f410
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 26 additions and 3 deletions

View File

@ -1,6 +1,8 @@
use rand::Rng;
use rfd::AsyncFileDialog;
use std::fs;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{Receiver, Sender, SyncSender};
use std::thread;
use std::time::{Duration, Instant};
@ -45,6 +47,7 @@ pub(crate) struct App {
persistent_data: PersistentData,
cli: Cli,
startup_time: Option<Instant>,
exiting: Arc<AtomicBool>,
exit_reason: ExitReason,
}
@ -68,14 +71,20 @@ impl App {
})
.expect("Error setting Ctrl-C handler");
let exiting = Arc::new(AtomicBool::new(false));
let rendering_app_event_scheduler = app_event_scheduler.clone();
let (start_render_sender, start_render_receiver) = std::sync::mpsc::sync_channel(1);
let exiting_clone = exiting.clone();
std::thread::spawn(move || {
let runtime = tokio::runtime::Runtime::new().unwrap();
loop {
let result = runtime.block_on(DesktopWrapper::execute_node_graph());
rendering_app_event_scheduler.schedule(AppEvent::NodeGraphExecutionResult(result));
let _ = start_render_receiver.recv_timeout(Duration::from_millis(10));
if exiting_clone.load(Ordering::Relaxed) {
break;
}
}
});
@ -107,8 +116,9 @@ impl App {
web_communication_startup_buffer: Vec::new(),
persistent_data,
cli,
exit_reason: ExitReason::Shutdown,
startup_time: None,
exiting,
exit_reason: ExitReason::Shutdown,
}
}
@ -118,6 +128,10 @@ impl App {
}
fn exit(&mut self, reason: Option<ExitReason>) {
if self.exiting.swap(true, Ordering::Relaxed) {
return;
}
let _ = self.start_render_sender.send(());
if let Some(reason) = reason {
self.exit_reason = reason;
}

View File

@ -53,7 +53,8 @@ impl CefContext for MultiThreadedCefContextProxy {
impl Drop for MultiThreadedCefContextProxy {
fn drop(&mut self) {
cef::shutdown();
// Force dropping underlying context on the UI thread
run_on_ui_thread(move || drop(CONTEXT.take()));
}
}

View File

@ -42,6 +42,10 @@ impl CefContext for SingleThreadedCefContext {
impl Drop for SingleThreadedCefContext {
fn drop(&mut self) {
tracing::debug!("Shutting down CEF");
// CEF wants us to close the browser before shutting down, otherwise it may run longer that necessary.
self.browser.host().unwrap().close_browser(1);
cef::shutdown();
// Sometimes some CEF processes still linger at this point and hold file handles to the cache directory.

View File

@ -26,7 +26,7 @@ impl MessageHandler<ViewportMessage, ()> for ViewportMessageHandler {
fn process_message(&mut self, message: ViewportMessage, responses: &mut VecDeque<Message>, _: ()) {
match message {
ViewportMessage::Update { x, y, width, height, scale } => {
assert_ne!(scale, 0., "Viewport scale cannot be zero");
assert!(scale > 0., "Viewport scale must be greater than zero");
self.scale = scale;
self.bounds = Bounds {

View File

@ -42,6 +42,10 @@ export function setupViewportResizeObserver(editor: Editor) {
// TODO: Consider passing physical sizes as well to eliminate pixel inaccuracies since width and height could be rounded differently
const scale = physicalWidth / logicalWidth;
if (!scale || scale <= 0) {
continue;
}
editor.handle.updateViewport(bounds.x, bounds.y, logicalWidth, logicalHeight, scale);
}
});