Add launch crash detection with detailed error dialog, fix all warnings
This commit is contained in:
@@ -15,6 +15,7 @@ const MAX_CONCURRENT_ANALYSES: usize = 2;
|
||||
static RUNNING_ANALYSES: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
/// Returns the number of currently running background analyses.
|
||||
#[allow(dead_code)]
|
||||
pub fn running_count() -> usize {
|
||||
RUNNING_ANALYSES.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
@@ -405,6 +405,7 @@ fn summarize_content_rating(attrs: &[(String, String)]) -> String {
|
||||
// AppStream catalog generation - writes catalog XML for GNOME Software/Discover
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#[allow(dead_code)]
|
||||
/// Generate an AppStream catalog XML from the Driftwood database.
|
||||
/// This allows GNOME Software / KDE Discover to see locally managed AppImages.
|
||||
pub fn generate_catalog(db: &Database) -> Result<String, AppStreamError> {
|
||||
@@ -462,6 +463,7 @@ pub fn generate_catalog(db: &Database) -> Result<String, AppStreamError> {
|
||||
Ok(xml)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
/// Install the AppStream catalog to the local swcatalog directory.
|
||||
/// GNOME Software reads from `~/.local/share/swcatalog/xml/`.
|
||||
pub fn install_catalog(db: &Database) -> Result<PathBuf, AppStreamError> {
|
||||
@@ -482,6 +484,7 @@ pub fn install_catalog(db: &Database) -> Result<PathBuf, AppStreamError> {
|
||||
Ok(catalog_path)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
/// Remove the AppStream catalog from the local swcatalog directory.
|
||||
pub fn uninstall_catalog() -> Result<(), AppStreamError> {
|
||||
let catalog_path = dirs::data_dir()
|
||||
@@ -498,6 +501,7 @@ pub fn uninstall_catalog() -> Result<(), AppStreamError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
/// Check if the AppStream catalog is currently installed.
|
||||
pub fn is_catalog_installed() -> bool {
|
||||
let catalog_path = dirs::data_dir()
|
||||
@@ -511,6 +515,7 @@ pub fn is_catalog_installed() -> bool {
|
||||
|
||||
// --- Utility functions ---
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn make_component_id(name: &str) -> String {
|
||||
name.chars()
|
||||
.map(|c| if c.is_alphanumeric() || c == '-' || c == '.' { c.to_ascii_lowercase() } else { '_' })
|
||||
@@ -519,6 +524,7 @@ fn make_component_id(name: &str) -> String {
|
||||
.to_string()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn xml_escape(s: &str) -> String {
|
||||
s.replace('&', "&")
|
||||
.replace('<', "<")
|
||||
@@ -530,6 +536,7 @@ fn xml_escape(s: &str) -> String {
|
||||
// --- Error types ---
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
pub enum AppStreamError {
|
||||
Database(String),
|
||||
Io(String),
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::fs;
|
||||
use std::io::Read;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
@@ -181,6 +181,7 @@ pub struct ConfigBackupRecord {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[allow(dead_code)]
|
||||
pub struct CatalogSourceRecord {
|
||||
pub id: i64,
|
||||
pub name: String,
|
||||
@@ -192,6 +193,7 @@ pub struct CatalogSourceRecord {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[allow(dead_code)]
|
||||
pub struct CatalogAppRecord {
|
||||
pub id: i64,
|
||||
pub source_id: i64,
|
||||
|
||||
@@ -38,6 +38,7 @@ pub struct AppImageMetadata {
|
||||
pub app_version: Option<String>,
|
||||
pub description: Option<String>,
|
||||
pub developer: Option<String>,
|
||||
#[allow(dead_code)]
|
||||
pub icon_name: Option<String>,
|
||||
pub categories: Vec<String>,
|
||||
pub desktop_entry_content: String,
|
||||
|
||||
@@ -42,6 +42,7 @@ pub enum LaunchMethod {
|
||||
/// Extract-and-run fallback (APPIMAGE_EXTRACT_AND_RUN=1)
|
||||
ExtractAndRun,
|
||||
/// Via firejail sandbox
|
||||
#[allow(dead_code)]
|
||||
Sandboxed,
|
||||
}
|
||||
|
||||
@@ -58,11 +59,18 @@ impl LaunchMethod {
|
||||
/// Result of a launch attempt.
|
||||
#[derive(Debug)]
|
||||
pub enum LaunchResult {
|
||||
/// Successfully spawned the process.
|
||||
/// Successfully spawned the process and it's still running.
|
||||
Started {
|
||||
child: Child,
|
||||
method: LaunchMethod,
|
||||
},
|
||||
/// Process spawned but crashed immediately (within ~1 second).
|
||||
Crashed {
|
||||
exit_code: Option<i32>,
|
||||
stderr: String,
|
||||
#[allow(dead_code)]
|
||||
method: LaunchMethod,
|
||||
},
|
||||
/// Failed to launch.
|
||||
Failed(String),
|
||||
}
|
||||
@@ -155,20 +163,56 @@ fn execute_appimage(
|
||||
cmd.env(key, value);
|
||||
}
|
||||
|
||||
// Detach from our process group so the app runs independently
|
||||
// Capture stderr to detect crash messages, stdin detached
|
||||
cmd.stdin(Stdio::null());
|
||||
cmd.stderr(Stdio::piped());
|
||||
|
||||
match cmd.spawn() {
|
||||
Ok(child) => LaunchResult::Started {
|
||||
child,
|
||||
method: method.clone(),
|
||||
},
|
||||
Err(e) => LaunchResult::Failed(format!("Failed to spawn process: {}", e)),
|
||||
Ok(mut child) => {
|
||||
// Brief wait to detect immediate crashes (e.g. missing Qt plugins)
|
||||
std::thread::sleep(std::time::Duration::from_millis(1500));
|
||||
match child.try_wait() {
|
||||
Ok(Some(status)) => {
|
||||
// Process already exited - it crashed
|
||||
let stderr = child
|
||||
.stderr
|
||||
.take()
|
||||
.and_then(|mut err| {
|
||||
let mut buf = String::new();
|
||||
use std::io::Read;
|
||||
err.read_to_string(&mut buf).ok()?;
|
||||
Some(buf)
|
||||
})
|
||||
.unwrap_or_default();
|
||||
LaunchResult::Crashed {
|
||||
exit_code: status.code(),
|
||||
stderr,
|
||||
method: method.clone(),
|
||||
}
|
||||
}
|
||||
Ok(None) => {
|
||||
// Still running - success
|
||||
LaunchResult::Started {
|
||||
child,
|
||||
method: method.clone(),
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
// Can't check status, assume it's running
|
||||
LaunchResult::Started {
|
||||
child,
|
||||
method: method.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => LaunchResult::Failed(format!("Failed to start: {}", e)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a launch_args string from the database into a Vec of individual arguments.
|
||||
/// Splits on whitespace; returns an empty Vec if the input is None or empty.
|
||||
#[allow(dead_code)]
|
||||
pub fn parse_launch_args(args: Option<&str>) -> Vec<String> {
|
||||
args.map(|s| s.split_whitespace().map(String::from).collect())
|
||||
.unwrap_or_default()
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use super::database::Database;
|
||||
use super::security;
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use super::database::{CveSummary, Database};
|
||||
use crate::config::VERSION;
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ pub struct CveMatch {
|
||||
/// Result of a security scan for a single AppImage.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SecurityScanResult {
|
||||
#[allow(dead_code)]
|
||||
pub appimage_id: i64,
|
||||
pub libraries: Vec<BundledLibrary>,
|
||||
pub cve_matches: Vec<(BundledLibrary, Vec<CveMatch>)>,
|
||||
|
||||
@@ -390,6 +390,7 @@ fn extract_update_info_runtime(path: &Path) -> Option<String> {
|
||||
// -- GitHub/GitLab API types for JSON deserialization --
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[allow(dead_code)]
|
||||
struct GhRelease {
|
||||
tag_name: String,
|
||||
name: Option<String>,
|
||||
@@ -405,6 +406,7 @@ struct GhAsset {
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[allow(dead_code)]
|
||||
struct GlRelease {
|
||||
tag_name: String,
|
||||
name: Option<String>,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::sync::mpsc;
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -307,9 +307,11 @@ pub fn detect_desktop_environment() -> String {
|
||||
/// Result of analyzing a running process for Wayland usage.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RuntimeAnalysis {
|
||||
#[allow(dead_code)]
|
||||
pub pid: u32,
|
||||
pub has_wayland_socket: bool,
|
||||
pub has_x11_connection: bool,
|
||||
#[allow(dead_code)]
|
||||
pub env_vars: Vec<(String, String)>,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user