Fixed auto update

This commit is contained in:
Uber Veng
2026-05-22 00:24:19 +07:00
parent cb85dfa039
commit 65e189c913
5 changed files with 25 additions and 19 deletions

View File

@@ -94,11 +94,12 @@ pub async fn check(api_base: &str, timeout_sec: u64) -> Result<Option<UpdateInfo
/// Downloads binary to temp file with streaming progress, atomically replaces
/// current exe, sets chmod 755.
/// progress_tx receives bytes downloaded so far.
/// Returns the path of the replaced executable (captured before rename so it
/// remains valid even after the old inode is marked "(deleted)" by the kernel).
pub async fn download_and_apply(
info: &UpdateInfo,
progress_tx: UnboundedSender<u64>,
) -> Result<()> {
) -> Result<std::path::PathBuf> {
let client = reqwest::Client::new();
let response = client
@@ -144,25 +145,28 @@ pub async fn download_and_apply(
std::fs::set_permissions(&tmp_path, perms).context("failed to set permissions")?;
}
// Atomically replace current exe
// Atomically replace current exe.
// current_exe is captured BEFORE this rename — after rename, /proc/self/exe
// on Linux returns the path with " (deleted)" appended, but the PathBuf we
// hold still refers to the correct filesystem path of the new binary.
std::fs::rename(&tmp_path, &current_exe).context("failed to replace current exe")?;
Ok(())
Ok(current_exe)
}
/// Replaces current process via execv (Unix). Never returns on success.
/// `exe_path` must be the path captured *before* the binary was replaced —
/// do NOT call std::env::current_exe() here, it returns "(deleted)" on Linux.
#[cfg(unix)]
pub fn exec_updated() -> ! {
pub fn exec_updated(exe_path: &std::path::Path) -> ! {
use std::os::unix::process::CommandExt;
let exe = std::env::current_exe().expect("failed to get current exe path");
let args: Vec<String> = std::env::args().collect();
let err = std::process::Command::new(&exe)
let err = std::process::Command::new(exe_path)
.args(&args[1..])
.exec();
// exec only returns if it failed
eprintln!("Failed to exec updated binary: {}", err);
std::process::exit(1);
}