From af70c1811bb08eb6769811009c4a7753bff4af74 Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Mon, 18 Mar 2019 11:52:04 +0100 Subject: [PATCH] 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 --- src/tools/daemon.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/tools/daemon.rs b/src/tools/daemon.rs index 0df1f2e5..b0e60d91 100644 --- a/src/tools/daemon.rs +++ b/src/tools/daemon.rs @@ -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 is unusable, so just use Box... @@ -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 { + let fd = var.parse::() + .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(), + )?) + } +}