fix: Single-Instance per User (Terminalserver-kompatibel)
Lock-File liegt in %APPDATA% (Windows) bzw ~/.config (Linux) - das ist pro User verschieden. Auf Terminalservern kann jeder User seine eigene Instanz haben. Verbesserungen: - Prueft ob der Prozess aus dem Lock-File noch lebt (PID-Check) statt nur ob die Datei existiert - Windows: tasklist /FI "PID eq X" - Linux: /proc/PID existiert? - Stale Lock-Files (Prozess abgestuerzt) werden ueberschrieben - Ohne .cloud Argument + andere Instanz laeuft -> sofort beenden - Mit .cloud Argument + andere Instanz -> delegieren und beenden Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4cc8de8a1a
commit
b653f9657a
|
|
@ -526,6 +526,8 @@ fn start_background_sync(
|
|||
// --- App Setup ---
|
||||
|
||||
/// Check if another instance is running. If yes, pass the .cloud file to it and exit.
|
||||
/// Single instance per user. On terminal servers each user gets their own
|
||||
/// instance because the lock file is in %APPDATA% (user-specific).
|
||||
fn handle_single_instance() {
|
||||
let config_dir = dirs::config_dir()
|
||||
.unwrap_or_else(|| PathBuf::from("."))
|
||||
|
|
@ -535,22 +537,48 @@ fn handle_single_instance() {
|
|||
let lock_file = config_dir.join("instance.lock");
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
|
||||
// If we have a .cloud file argument and another instance is running
|
||||
if args.len() > 1 && args[1].ends_with(".cloud") {
|
||||
if lock_file.exists() {
|
||||
// Write the .cloud path to a request file for the running instance
|
||||
let request_file = config_dir.join("open_request.txt");
|
||||
std::fs::write(&request_file, &args[1]).ok();
|
||||
eprintln!("[SingleInstance] Passing {} to running instance", args[1]);
|
||||
std::process::exit(0);
|
||||
}
|
||||
// Check if another instance of THIS USER is running
|
||||
let other_running = if lock_file.exists() {
|
||||
if let Ok(pid_str) = std::fs::read_to_string(&lock_file) {
|
||||
let pid = pid_str.trim().parse::<u32>().unwrap_or(0);
|
||||
if pid > 0 && pid != std::process::id() {
|
||||
// Check if that process is still alive
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
std::process::Command::new("tasklist")
|
||||
.args(["/FI", &format!("PID eq {}", pid), "/NH"])
|
||||
.output()
|
||||
.map(|o| String::from_utf8_lossy(&o.stdout).contains(&pid.to_string()))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
{
|
||||
std::path::Path::new(&format!("/proc/{}", pid)).exists()
|
||||
}
|
||||
} else { false }
|
||||
} else { false }
|
||||
} else { false };
|
||||
|
||||
// If .cloud file argument and another instance runs -> delegate and exit
|
||||
if args.len() > 1 && args[1].ends_with(".cloud") && other_running {
|
||||
let request_file = config_dir.join("open_request.txt");
|
||||
std::fs::write(&request_file, &args[1]).ok();
|
||||
eprintln!("[SingleInstance] Delegated {} to running instance (PID in lock)", args[1]);
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
// Write our lock file
|
||||
std::fs::write(&lock_file, std::process::id().to_string()).ok();
|
||||
// If no .cloud argument but another instance runs -> just bring it to front and exit
|
||||
if other_running && args.len() <= 1 {
|
||||
eprintln!("[SingleInstance] Already running, exiting");
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
// We are the main instance - write our PID
|
||||
std::fs::write(&lock_file, std::process::id().to_string()).ok();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
handle_single_instance();
|
||||
|
|
|
|||
Loading…
Reference in New Issue