tools::daemon: fetch exe name in the beginning

We get the path to our executable via a readlink() on
"/proc/self/exe", which appends a " (deleted)" during
package reloads.

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2020-06-22 10:20:51 +02:00
parent b28253d650
commit dc2ef2b54f
1 changed files with 18 additions and 15 deletions

View File

@ -31,6 +31,7 @@ pub trait Reloadable: Sized {
#[derive(Default)] #[derive(Default)]
pub struct Reloader { pub struct Reloader {
pre_exec: Vec<PreExecEntry>, pre_exec: Vec<PreExecEntry>,
self_exe: CString,
} }
// Currently we only need environment variables for storage, but in theory we could also add // Currently we only need environment variables for storage, but in theory we could also add
@ -41,10 +42,17 @@ struct PreExecEntry {
} }
impl Reloader { impl Reloader {
pub fn new() -> Self { pub fn new() -> Result<Self, Error> {
Self { Ok(Self {
pre_exec: Vec::new(), pre_exec: Vec::new(),
}
// Get the path to our executable as CString
self_exe: CString::new(
std::fs::read_link("/proc/self/exe")?
.into_os_string()
.as_bytes()
)?
})
} }
/// Restore an object from an environment variable of the given name, or, if none exists, uses /// Restore an object from an environment variable of the given name, or, if none exists, uses
@ -78,13 +86,6 @@ impl Reloader {
} }
pub fn fork_restart(self) -> Result<(), Error> { pub fn fork_restart(self) -> Result<(), Error> {
// Get the path to our executable as CString
let exe = CString::new(
std::fs::read_link("/proc/self/exe")?
.into_os_string()
.as_bytes()
)?;
// Get our parameters as Vec<CString> // Get our parameters as Vec<CString>
let args = std::env::args_os(); let args = std::env::args_os();
let mut new_args = Vec::with_capacity(args.len()); let mut new_args = Vec::with_capacity(args.len());
@ -117,10 +118,11 @@ impl Reloader {
} }
} }
std::mem::drop(pout); std::mem::drop(pout);
self.do_exec(exe, new_args) self.do_reexec(new_args)
}) })
{ {
Ok(_) => eprintln!("do_exec returned unexpectedly!"), Ok(Ok(())) => eprintln!("do_reexec returned!"),
Ok(Err(err)) => eprintln!("do_reexec failed: {}", err),
Err(_) => eprintln!("panic in re-exec"), Err(_) => eprintln!("panic in re-exec"),
} }
} }
@ -162,12 +164,13 @@ impl Reloader {
} }
} }
fn do_exec(self, exe: CString, args: Vec<CString>) -> Result<(), Error> { fn do_reexec(self, args: Vec<CString>) -> Result<(), Error> {
let exe = self.self_exe.clone();
self.pre_exec()?; self.pre_exec()?;
nix::unistd::setsid()?; nix::unistd::setsid()?;
let args: Vec<&std::ffi::CStr> = args.iter().map(|s| s.as_ref()).collect(); let args: Vec<&std::ffi::CStr> = args.iter().map(|s| s.as_ref()).collect();
nix::unistd::execvp(&exe, &args)?; nix::unistd::execvp(&exe, &args)?;
Ok(()) panic!("exec misbehaved");
} }
} }
@ -223,7 +226,7 @@ where
F: FnOnce(tokio::net::TcpListener, NotifyReady) -> Result<S, Error>, F: FnOnce(tokio::net::TcpListener, NotifyReady) -> Result<S, Error>,
S: Future<Output = ()>, S: Future<Output = ()>,
{ {
let mut reloader = Reloader::new(); let mut reloader = Reloader::new()?;
let listener: tokio::net::TcpListener = reloader.restore( let listener: tokio::net::TcpListener = reloader.restore(
"PROXMOX_BACKUP_LISTEN_FD", "PROXMOX_BACKUP_LISTEN_FD",