Add launch crash detection with detailed error dialog, fix all warnings
Detect AppImages that crash immediately after spawning (within 1.5s) by capturing stderr and using try_wait(). Show a full AlertDialog with a plain-text explanation, scrollable error output, and a copy-to-clipboard button. Covers Qt plugin errors, missing libraries, segfaults, permission issues, and display connection failures. Move launch operations to background threads in both the detail view and context menu to avoid blocking the UI during the 1.5s crash detection window. Suppress all 57 compiler warnings across future-use modules (backup, notification, report, watcher) and individual unused fields/variants in other core modules.
This commit is contained in:
@@ -79,59 +79,67 @@ pub fn build_detail_page(record: &AppImageRecord, db: &Rc<Database>) -> adw::Nav
|
||||
]);
|
||||
let record_id = record.id;
|
||||
let path = record.path.clone();
|
||||
let app_name_launch = record.app_name.clone().unwrap_or_else(|| record.filename.clone());
|
||||
let db_launch = db.clone();
|
||||
launch_button.connect_clicked(move |_| {
|
||||
let appimage_path = std::path::Path::new(&path);
|
||||
let result = launcher::launch_appimage(
|
||||
&db_launch,
|
||||
record_id,
|
||||
appimage_path,
|
||||
"gui_detail",
|
||||
&[],
|
||||
&[],
|
||||
);
|
||||
match result {
|
||||
launcher::LaunchResult::Started { child, method } => {
|
||||
let pid = child.id();
|
||||
log::info!("Launched AppImage: {} (PID: {}, method: {})", path, pid, method.as_str());
|
||||
let toast_launch = toast_overlay.clone();
|
||||
launch_button.connect_clicked(move |btn| {
|
||||
btn.set_sensitive(false);
|
||||
let btn_ref = btn.clone();
|
||||
let path = path.clone();
|
||||
let app_name = app_name_launch.clone();
|
||||
let db_launch = db_launch.clone();
|
||||
let toast_ref = toast_launch.clone();
|
||||
glib::spawn_future_local(async move {
|
||||
let path_bg = path.clone();
|
||||
let result = gio::spawn_blocking(move || {
|
||||
let appimage_path = std::path::Path::new(&path_bg);
|
||||
launcher::launch_appimage(
|
||||
&Database::open().expect("DB open"),
|
||||
record_id,
|
||||
appimage_path,
|
||||
"gui_detail",
|
||||
&[],
|
||||
&[],
|
||||
)
|
||||
}).await;
|
||||
|
||||
let db_wayland = db_launch.clone();
|
||||
let path_clone = path.clone();
|
||||
glib::spawn_future_local(async move {
|
||||
glib::timeout_future(std::time::Duration::from_secs(3)).await;
|
||||
btn_ref.set_sensitive(true);
|
||||
match result {
|
||||
Ok(launcher::LaunchResult::Started { child, method }) => {
|
||||
let pid = child.id();
|
||||
log::info!("Launched: {} (PID: {}, method: {})", path, pid, method.as_str());
|
||||
|
||||
let analysis_result = gio::spawn_blocking(move || {
|
||||
wayland::analyze_running_process(pid)
|
||||
}).await;
|
||||
|
||||
match analysis_result {
|
||||
Ok(Ok(analysis)) => {
|
||||
let status_label = analysis.status_label();
|
||||
let db_wayland = db_launch.clone();
|
||||
let path_clone = path.clone();
|
||||
glib::spawn_future_local(async move {
|
||||
glib::timeout_future(std::time::Duration::from_secs(3)).await;
|
||||
let analysis_result = gio::spawn_blocking(move || {
|
||||
wayland::analyze_running_process(pid)
|
||||
}).await;
|
||||
if let Ok(Ok(analysis)) = analysis_result {
|
||||
let status_str = analysis.as_status_str();
|
||||
log::info!(
|
||||
"Runtime Wayland analysis for {} (PID {}): {} (wayland_socket={}, x11={}, env_vars={})",
|
||||
path_clone, analysis.pid, status_label,
|
||||
analysis.has_wayland_socket,
|
||||
analysis.has_x11_connection,
|
||||
analysis.env_vars.len(),
|
||||
);
|
||||
db_wayland.update_runtime_wayland_status(
|
||||
record_id, status_str,
|
||||
).ok();
|
||||
log::info!("Runtime Wayland: {} -> {}", path_clone, analysis.status_label());
|
||||
db_wayland.update_runtime_wayland_status(record_id, status_str).ok();
|
||||
}
|
||||
Ok(Err(e)) => {
|
||||
log::debug!("Runtime analysis failed for PID {}: {}", pid, e);
|
||||
}
|
||||
Err(_) => {
|
||||
log::debug!("Runtime analysis task failed for PID {}", pid);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
Ok(launcher::LaunchResult::Crashed { exit_code, stderr, .. }) => {
|
||||
log::error!("App crashed on launch (exit {}): {}", exit_code.unwrap_or(-1), stderr);
|
||||
widgets::show_crash_dialog(&btn_ref, &app_name, exit_code, &stderr);
|
||||
}
|
||||
Ok(launcher::LaunchResult::Failed(msg)) => {
|
||||
log::error!("Failed to launch: {}", msg);
|
||||
let toast = adw::Toast::builder()
|
||||
.title(&format!("Could not launch: {}", msg))
|
||||
.timeout(5)
|
||||
.build();
|
||||
toast_ref.add_toast(toast);
|
||||
}
|
||||
Err(_) => {
|
||||
log::error!("Launch task panicked");
|
||||
}
|
||||
}
|
||||
launcher::LaunchResult::Failed(msg) => {
|
||||
log::error!("Failed to launch: {}", msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
header.pack_end(&launch_button);
|
||||
|
||||
@@ -1025,7 +1033,7 @@ fn build_system_tab(record: &AppImageRecord, db: &Rc<Database>, toast_overlay: &
|
||||
match result {
|
||||
Ok(analysis) => {
|
||||
let toolkit_label = analysis.toolkit.label();
|
||||
let lib_count = analysis.libraries_found.len();
|
||||
let _lib_count = analysis.libraries_found.len();
|
||||
row_clone.set_subtitle(&format!(
|
||||
"Built with: {}",
|
||||
toolkit_label,
|
||||
@@ -1062,13 +1070,10 @@ fn build_system_tab(record: &AppImageRecord, db: &Rc<Database>, toast_overlay: &
|
||||
compat_group.add(&runtime_row);
|
||||
}
|
||||
|
||||
// FUSE status
|
||||
// FUSE status - always use live system detection (the stored fuse_status
|
||||
// is per-app AppImageFuseStatus, not the system-level FuseStatus)
|
||||
let fuse_system = fuse::detect_system_fuse();
|
||||
let fuse_status = record
|
||||
.fuse_status
|
||||
.as_deref()
|
||||
.map(FuseStatus::from_str)
|
||||
.unwrap_or(fuse_system.status.clone());
|
||||
let fuse_status = fuse_system.status.clone();
|
||||
|
||||
let fuse_row = adw::ActionRow::builder()
|
||||
.title("App mounting")
|
||||
@@ -1824,3 +1829,4 @@ fn fetch_favicon_async(url: &str, image: >k::Image) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user