From a05773b7d0a5e66bd6555546e70dfd0636a285d9 Mon Sep 17 00:00:00 2001 From: mwrock Date: Thu, 2 Apr 2020 15:21:16 -0700 Subject: [PATCH 1/2] fix local builds unable to link against zmq Signed-off-by: mwrock --- .expeditor/scripts/verify/shared.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.expeditor/scripts/verify/shared.ps1 b/.expeditor/scripts/verify/shared.ps1 index b2da366fc6..cee4d7cd3c 100644 --- a/.expeditor/scripts/verify/shared.ps1 +++ b/.expeditor/scripts/verify/shared.ps1 @@ -54,7 +54,7 @@ function Initialize-Environment { $env:PATH = New-PathString -StartingPath $env:PATH -Path "$protobufDir\bin;$zeromqDir\bin;$libarchiveDir\bin;$libsodiumDir\bin;$zlibDir\bin;$xzDir\bin;$opensslDir\bin" $vsDir = & hab pkg path core/visual-cpp-build-tools-2015 - $env:LIB = (Get-Content "$vsDir\LIB_DIRS") + $env:LIB = "$(Get-Content "$vsDir\LIB_DIRS");$env:LIBZMQ_PREFIX\lib" $env:INCLUDE = (Get-Content "$vsDir\INCLUDE_DIRS") $env:PATH = New-PathString -StartingPath $env:PATH -Path (Get-Content "$vsDir\PATH") } From 83ec31299470f8dc83ee5386fa5c2eaf87bc495e Mon Sep 17 00:00:00 2001 From: mwrock Date: Thu, 2 Apr 2020 15:50:58 -0700 Subject: [PATCH 2/2] explicitly clear HANDLE_FLAG_INHERIT of cloned sockets on windows Signed-off-by: mwrock --- Cargo.lock | 1 + components/butterfly/Cargo.toml | 3 +++ components/butterfly/src/error.rs | 2 ++ components/butterfly/src/server.rs | 31 ++++++++++++++++++++++++++++-- 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 24b9358120..350dcd0f64 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1337,6 +1337,7 @@ dependencies = [ "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "zmq 0.8.3 (git+https://github.com/habitat-sh/rust-zmq?branch=v0.8-symlinks-removed)", ] diff --git a/components/butterfly/Cargo.toml b/components/butterfly/Cargo.toml index b169c8d870..aff99d9a76 100644 --- a/components/butterfly/Cargo.toml +++ b/components/butterfly/Cargo.toml @@ -33,6 +33,9 @@ toml = { version = "*", default-features = false } uuid = { version = "*", features = ["v4"] } zmq = { git = "https://github.com/habitat-sh/rust-zmq", branch = "v0.8-symlinks-removed" } +[target.'cfg(windows)'.dependencies] +winapi = { version = "*", features = ["handleapi", "winbase"] } + [dev-dependencies] mktemp = "*" diff --git a/components/butterfly/src/error.rs b/components/butterfly/src/error.rs index 6cbd40e2cc..f82b87d730 100644 --- a/components/butterfly/src/error.rs +++ b/components/butterfly/src/error.rs @@ -26,6 +26,7 @@ pub enum Error { IncarnationParse(PathBuf, num::ParseIntError), InvalidRumorShareLimit, NonExistentRumor(String, String), + OsError(io::Error), ProtocolMismatch(&'static str), ServiceConfigDecode(String, toml::de::Error), ServiceConfigNotUtf8(String, str::Utf8Error), @@ -79,6 +80,7 @@ impl fmt::Display for Error { format!("Non existent rumor asked to be written to bytes: {} {}", member_id, rumor_id) } + Error::OsError(ref err) => format!("OS error: {}", err), Error::ProtocolMismatch(ref field) => { format!("Received an unsupported or bad protocol message. Missing field: {}", field) diff --git a/components/butterfly/src/server.rs b/components/butterfly/src/server.rs index 6a8a0c86ba..22be3358eb 100644 --- a/components/butterfly/src/server.rs +++ b/components/butterfly/src/server.rs @@ -501,11 +501,11 @@ impl Server { socket.set_write_timeout(Some(Duration::from_millis(1000))) .map_err(Error::SocketSetReadTimeout)?; - self.socket = Some(socket.try_clone()?); + self.socket = Some(clone_socket(&socket)?); inbound::spawn_thread(format!("inbound-{}", self.name()), self.clone(), - socket.try_clone()?, + clone_socket(&socket)?, tx_outbound)?; outbound::spawn_thread(format!("outbound-{}", self.name()), @@ -1280,6 +1280,33 @@ fn persist_loop(server: &Server) -> ! { } } +/// There is a bug which surfaced in rust 1.38 where cloned sockets on windows +/// get inherited by child processes and remain open even after the process that +/// created the socket terminates as long as the child processes remain alive. +/// See https://github.com/rust-lang/rust/issues/70719. +/// Until this is fixed, we explicitly clear the HANDLE_FLAG_INHERIT of the +/// socket's handle. +#[cfg(windows)] +fn clone_socket(socket: &UdpSocket) -> Result { + use std::os::windows::io::AsRawSocket; + use winapi::um::{handleapi, + winbase, + winnt}; + + let cloned = socket.try_clone()?; + match unsafe { + handleapi::SetHandleInformation(cloned.as_raw_socket() as winnt::HANDLE, + winbase::HANDLE_FLAG_INHERIT, + 0) + } { + 0 => Err(Error::OsError(io::Error::last_os_error())), + _ => Ok(cloned), + } +} + +#[cfg(unix)] +fn clone_socket(socket: &UdpSocket) -> std::io::Result { socket.try_clone() } + /// This is a proxy struct to represent what information we're writing to the dat file, and /// therefore what information gets sent out via the HTTP API. Right now, we're just wrapping the /// actual Server struct, but this will give us something we can refactor against without