tools: implement ReexecContinue for tokio's TcpListener

This is the only thing we currently need to keep alive for
reloads.

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2019-03-18 11:52:04 +01:00
parent 4422ba2c7f
commit af70c1811b

View File

@ -1,12 +1,14 @@
//! Helpers for daemons/services.
use std::ffi::CString;
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::os::unix::ffi::OsStrExt;
use std::panic::UnwindSafe;
use failure::*;
use tokio::prelude::*;
use crate::tools::fd_change_cloexec;
use crate::tools::signalfd::{SigSet, SignalFd};
// Unfortunately FnBox is nightly-only and Box<FnOnce> is unusable, so just use Box<Fn>...
@ -168,3 +170,28 @@ where
.and_then(|si_res| si_res)
)
}
// For now all we need to do is store and reuse a tcp listening socket:
impl ReexecContinue for tokio::net::TcpListener {
// NOTE: The socket must not be closed when the store-function is called:
// FIXME: We could become "independent" of the TcpListener and its reference to the file
// descriptor by `dup()`ing it (and check if the listener still exists via kcmp()?)
fn get_store_func(&self) -> BoxedStoreFunc {
let fd = self.as_raw_fd();
Box::new(move || {
fd_change_cloexec(fd, false)?;
Ok(fd.to_string())
})
}
fn restore(var: &str) -> Result<Self, Error> {
let fd = var.parse::<u32>()
.map_err(|e| format_err!("invalid file descriptor: {}", e))?
as RawFd;
fd_change_cloexec(fd, true)?;
Ok(Self::from_std(
unsafe { std::net::TcpListener::from_raw_fd(fd) },
&tokio::reactor::Handle::default(),
)?)
}
}