mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-10-14 21:20:48 +08:00
fix(singleton): let a restart-spawned child take over the instance lock
The secondary wait only polled the notify endpoint, which a restarting instance has already shut down before spawning its successor, so a child that lost the spawn-vs-exit race could never acquire the freed lock and died after 20s behind a startup-failure dialog. Retry try_lock_instance on every poll so the child promotes as soon as the old process exits. Double-launch handoff and wedged-holder timeout behavior are unchanged.
This commit is contained in:
@@ -54,7 +54,16 @@ pub async fn check_singleton() -> Result<SingletonDisposition> {
|
||||
.context("failed to initialize singleton lock")?;
|
||||
if !try_lock_instance(&lock).context("failed to acquire singleton lock")? {
|
||||
let deadline = std::time::Instant::now() + Duration::from_secs(20);
|
||||
while std::time::Instant::now() < deadline {
|
||||
loop {
|
||||
if std::time::Instant::now() >= deadline {
|
||||
bail!("another app instance is starting");
|
||||
}
|
||||
// A restarting instance releases this lock only after spawning this
|
||||
// process, and its embedded server is already down, so waiting on
|
||||
// the notify probe alone can never promote this instance.
|
||||
if try_lock_instance(&lock).context("failed to acquire singleton lock")? {
|
||||
break;
|
||||
}
|
||||
if let Ok(record) = read_instance_record(&record_path)
|
||||
&& notify_existing_instance(&record).await
|
||||
{
|
||||
@@ -62,7 +71,6 @@ pub async fn check_singleton() -> Result<SingletonDisposition> {
|
||||
}
|
||||
tokio::time::sleep(Duration::from_millis(50)).await;
|
||||
}
|
||||
bail!("another app instance is starting");
|
||||
}
|
||||
|
||||
let preferred = read_instance_record(&record_path).ok().map(|record| record.port);
|
||||
|
||||
Reference in New Issue
Block a user