linux: Store binary path before restart to handle deleted binary file (#11568)

This fixes restart after updates not working on Linux.

On Linux we can't reliably get the binary path after an update, because
the original binary was deleted and the path will contain ` (deleted)`.

See: https://github.com/rust-lang/rust/issues/69343

We *could* strip ` (deleted)` off, but that feels nasty. So instead we
save the original binary path, before we do the installation, then
restart.

Later on, we can also change this to be a _new_ binary path returned by
the installers, which we then have to start.


Release Notes:

- N/A
This commit is contained in:
Thorsten Ball 2024-05-08 19:13:28 +02:00 committed by GitHub
parent d2cec0221b
commit dbebb40956
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 49 additions and 25 deletions

View file

@ -642,8 +642,8 @@ impl AppContext {
}
/// Restart the application.
pub fn restart(&self) {
self.platform.restart()
pub fn restart(&self, binary_path: Option<PathBuf>) {
self.platform.restart(binary_path)
}
/// Returns the local timezone at the platform level.

View file

@ -98,7 +98,7 @@ pub(crate) trait Platform: 'static {
fn run(&self, on_finish_launching: Box<dyn 'static + FnOnce()>);
fn quit(&self);
fn restart(&self);
fn restart(&self, binary_path: Option<PathBuf>);
fn activate(&self, ignoring_other_apps: bool);
fn hide(&self);
fn hide_other_apps(&self);

View file

@ -136,17 +136,21 @@ impl<P: LinuxClient + 'static> Platform for P {
self.with_common(|common| common.signal.stop());
}
fn restart(&self) {
fn restart(&self, binary_path: Option<PathBuf>) {
use std::os::unix::process::CommandExt as _;
// get the process id of the current process
let app_pid = std::process::id().to_string();
// get the path to the executable
let app_path = match self.app_path() {
Ok(path) => path,
Err(err) => {
log::error!("Failed to get app path: {:?}", err);
return;
let app_path = if let Some(path) = binary_path {
path
} else {
match self.app_path() {
Ok(path) => path,
Err(err) => {
log::error!("Failed to get app path: {:?}", err);
return;
}
}
};

View file

@ -396,7 +396,7 @@ impl Platform for MacPlatform {
}
}
fn restart(&self) {
fn restart(&self, _binary_path: Option<PathBuf>) {
use std::os::unix::process::CommandExt as _;
let app_pid = std::process::id().to_string();

View file

@ -140,7 +140,7 @@ impl Platform for TestPlatform {
fn quit(&self) {}
fn restart(&self) {
fn restart(&self, _: Option<PathBuf>) {
unimplemented!()
}

View file

@ -268,7 +268,7 @@ impl Platform for WindowsPlatform {
.detach();
}
fn restart(&self) {
fn restart(&self, _: Option<PathBuf>) {
let pid = std::process::id();
let Some(app_path) = self.app_path().log_err() else {
return;