Skip to content

Commit

Permalink
Fix Docker M1 Mac watcher failure and release v0.17.5
Browse files Browse the repository at this point in the history
  • Loading branch information
chipsenkbeil committed Aug 18, 2022
1 parent 7849567 commit 3b3e744
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 38 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
## [0.17.5] - 2022-08-18
### Fixed

- Handle `RecommendedWatcher` failing with an unsupported OS function on M1 Mac
architecture running a Linux container via Docker
([notify #423](https://github.com/notify-rs/notify/issues/423))

## [0.17.4] - 2022-08-18
### Fixed

Expand Down
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "distant"
description = "Operate on a remote computer through file and process manipulation"
categories = ["command-line-utilities"]
keywords = ["cli"]
version = "0.17.4"
version = "0.17.5"
authors = ["Chip Senkbeil <[email protected]>"]
edition = "2021"
homepage = "https://github.com/chipsenkbeil/distant"
Expand Down Expand Up @@ -32,7 +32,7 @@ clap_complete = "3.2.3"
config = { version = "0.13.2", default-features = false, features = ["toml"] }
derive_more = { version = "0.99.17", default-features = false, features = ["display", "from", "error", "is_variant"] }
dialoguer = { version = "0.10.2", default-features = false }
distant-core = { version = "=0.17.4", path = "distant-core", features = ["clap", "schemars"] }
distant-core = { version = "=0.17.5", path = "distant-core", features = ["clap", "schemars"] }
directories = "4.0.1"
flexi_logger = "0.23.0"
indoc = "1.0.7"
Expand All @@ -54,7 +54,7 @@ winsplit = "0.1.0"
whoami = "1.2.1"

# Optional native SSH functionality
distant-ssh2 = { version = "=0.17.4", path = "distant-ssh2", default-features = false, features = ["serde"], optional = true }
distant-ssh2 = { version = "=0.17.5", path = "distant-ssh2", default-features = false, features = ["serde"], optional = true }

[target.'cfg(unix)'.dependencies]
fork = "0.1.19"
Expand Down
4 changes: 2 additions & 2 deletions distant-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "distant-core"
description = "Core library for distant, enabling operation on a remote computer through file and process manipulation"
categories = ["network-programming"]
keywords = ["api", "async"]
version = "0.17.4"
version = "0.17.5"
authors = ["Chip Senkbeil <[email protected]>"]
edition = "2021"
homepage = "https://github.com/chipsenkbeil/distant"
Expand All @@ -19,7 +19,7 @@ async-trait = "0.1.57"
bitflags = "1.3.2"
bytes = "1.2.1"
derive_more = { version = "0.99.17", default-features = false, features = ["as_mut", "as_ref", "deref", "deref_mut", "display", "from", "error", "into", "into_iterator", "is_variant", "try_into"] }
distant-net = { version = "=0.17.4", path = "../distant-net" }
distant-net = { version = "=0.17.5", path = "../distant-net" }
futures = "0.3.21"
hex = "0.4.3"
log = "0.4.17"
Expand Down
77 changes: 51 additions & 26 deletions distant-core/src/api/local/state/watcher.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::{constants::SERVER_WATCHER_CAPACITY, data::ChangeKind, ConnectionId};
use log::*;
use notify::{
Config as WatcherConfig, Error as WatcherError, Event as WatcherEvent, RecommendedWatcher,
RecursiveMode, Watcher,
Config as WatcherConfig, Error as WatcherError, ErrorKind as WatcherErrorKind,
Event as WatcherEvent, PollWatcher, RecursiveMode, Watcher,
};
use std::{
collections::HashMap,
Expand Down Expand Up @@ -41,10 +41,32 @@ impl WatcherState {
// with a large volume of watch requests
let (tx, rx) = mpsc::channel(SERVER_WATCHER_CAPACITY);

let mut watcher = {
let tx = tx.clone();
notify::recommended_watcher(move |res| {
match tx.try_send(match res {
macro_rules! configure_and_spawn {
($watcher:ident) => {{
// Attempt to configure watcher, but don't fail if these configurations fail
match $watcher.configure(WatcherConfig::PreciseEvents(true)) {
Ok(true) => debug!("Watcher configured for precise events"),
Ok(false) => debug!("Watcher not configured for precise events",),
Err(x) => error!("Watcher configuration for precise events failed: {}", x),
}

// Attempt to configure watcher, but don't fail if these configurations fail
match $watcher.configure(WatcherConfig::NoticeEvents(true)) {
Ok(true) => debug!("Watcher configured for notice events"),
Ok(false) => debug!("Watcher not configured for notice events",),
Err(x) => error!("Watcher configuration for notice events failed: {}", x),
}

Ok(Self {
channel: WatcherChannel { tx },
task: tokio::spawn(watcher_task($watcher, rx)),
})
}};
}

macro_rules! event_handler {
($tx:ident) => {
move |res| match $tx.try_send(match res {
Ok(x) => InnerWatcherMsg::Event { ev: x },
Err(x) => InnerWatcherMsg::Error { err: x },
}) {
Expand All @@ -59,28 +81,31 @@ impl WatcherState {
warn!("Skipping watch event because watcher channel closed");
}
}
})
.map_err(|x| io::Error::new(io::ErrorKind::Other, x))?
};

// Attempt to configure watcher, but don't fail if these configurations fail
match watcher.configure(WatcherConfig::PreciseEvents(true)) {
Ok(true) => debug!("Watcher configured for precise events"),
Ok(false) => debug!("Watcher not configured for precise events",),
Err(x) => error!("Watcher configuration for precise events failed: {}", x),
};
}

// Attempt to configure watcher, but don't fail if these configurations fail
match watcher.configure(WatcherConfig::NoticeEvents(true)) {
Ok(true) => debug!("Watcher configured for notice events"),
Ok(false) => debug!("Watcher not configured for notice events",),
Err(x) => error!("Watcher configuration for notice events failed: {}", x),
}
let tx = tx.clone();
let result = {
let tx = tx.clone();
notify::recommended_watcher(event_handler!(tx))
};

Ok(Self {
channel: WatcherChannel { tx },
task: tokio::spawn(watcher_task(watcher, rx)),
})
match result {
Ok(mut watcher) => configure_and_spawn!(watcher),
Err(x) => match x.kind {
// notify-rs has a bug on Mac M1 with Docker and Linux, so we detect that error
// and fall back to the poll watcher if this occurs
//
// https://github.com/notify-rs/notify/issues/423
WatcherErrorKind::Io(x) if x.raw_os_error() == Some(38) => {
warn!("Recommended watcher is unsupported! Falling back to polling watcher!");
let mut watcher = PollWatcher::new(event_handler!(tx))
.map_err(|x| io::Error::new(io::ErrorKind::Other, x))?;
configure_and_spawn!(watcher)
}
_ => Err(io::Error::new(io::ErrorKind::Other, x)),
},
}
}

pub fn clone_channel(&self) -> WatcherChannel {
Expand Down Expand Up @@ -163,7 +188,7 @@ enum InnerWatcherMsg {
},
}

async fn watcher_task(mut watcher: RecommendedWatcher, mut rx: mpsc::Receiver<InnerWatcherMsg>) {
async fn watcher_task(mut watcher: impl Watcher, mut rx: mpsc::Receiver<InnerWatcherMsg>) {
// TODO: Optimize this in some way to be more performant than
// checking every path whenever an event comes in
let mut registered_paths: Vec<RegisteredPath> = Vec::new();
Expand Down
2 changes: 1 addition & 1 deletion distant-net/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "distant-net"
description = "Network library for distant, providing implementations to support client/server architecture"
categories = ["network-programming"]
keywords = ["api", "async"]
version = "0.17.4"
version = "0.17.5"
authors = ["Chip Senkbeil <[email protected]>"]
edition = "2021"
homepage = "https://github.com/chipsenkbeil/distant"
Expand Down
4 changes: 2 additions & 2 deletions distant-ssh2/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "distant-ssh2"
description = "Library to enable native ssh-2 protocol for use with distant sessions"
categories = ["network-programming"]
version = "0.17.4"
version = "0.17.5"
authors = ["Chip Senkbeil <[email protected]>"]
edition = "2021"
homepage = "https://github.com/chipsenkbeil/distant"
Expand All @@ -20,7 +20,7 @@ async-compat = "0.2.1"
async-once-cell = "0.4.2"
async-trait = "0.1.57"
derive_more = { version = "0.99.17", default-features = false, features = ["display", "error"] }
distant-core = { version = "=0.17.4", path = "../distant-core" }
distant-core = { version = "=0.17.5", path = "../distant-core" }
futures = "0.3.21"
hex = "0.4.3"
log = "0.4.17"
Expand Down

0 comments on commit 3b3e744

Please sign in to comment.