diff --git a/src/common.rs b/src/common.rs index 60d163433..5b56c8ed5 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1081,7 +1081,7 @@ pub fn has_working_tty_timestamps() -> bool { if cfg!(target_os = "windows") { false } else if cfg!(target_os = "linux") { - !is_windows_subsystem_for_linux() + !is_windows_subsystem_for_linux(WSL::V1) } else { true } @@ -1462,7 +1462,7 @@ pub fn fish_setlocale() { ELLIPSIS_STRING.store(LL!("...")); } - if is_windows_subsystem_for_linux() { + if is_windows_subsystem_for_linux(WSL::Any) { // neither of \u23CE and \u25CF can be displayed in the default fonts on Windows, though // they can be *encoded* just fine. Use alternative glyphs. OMITTED_NEWLINE_STR.store(LL!("\u{00b6}")); // "pilcrow" @@ -1675,12 +1675,20 @@ pub fn subslice_position(a: &[T], b: &[T]) -> Option { a.windows(b.len()).position(|aw| aw == b) } +#[derive(Copy, Debug, Clone, PartialEq, Eq)] +pub enum WSL { + Any, + V1, + V2, +} + /// Determines if we are running under Microsoft's Windows Subsystem for Linux to work around /// some known limitations and/or bugs. /// /// See https://github.com/Microsoft/WSL/issues/423 and Microsoft/WSL#2997 +#[inline(always)] #[cfg(not(target_os = "linux"))] -pub fn is_windows_subsystem_for_linux() -> bool { +pub fn is_windows_subsystem_for_linux(_: WSL) -> bool { false } @@ -1689,8 +1697,9 @@ pub fn is_windows_subsystem_for_linux() -> bool { /// /// See https://github.com/Microsoft/WSL/issues/423 and Microsoft/WSL#2997 #[cfg(target_os = "linux")] -pub fn is_windows_subsystem_for_linux() -> bool { - static RESULT: once_cell::race::OnceBool = once_cell::race::OnceBool::new(); +pub fn is_windows_subsystem_for_linux(v: WSL) -> bool { + use std::sync::OnceLock; + static RESULT: OnceLock> = OnceLock::new(); // This is called post-fork from [`report_setpgid_error()`], so the fast path must not involve // any allocations or mutexes. We can't rely on all the std functions to be alloc-free in both @@ -1705,16 +1714,21 @@ pub fn is_windows_subsystem_for_linux() -> bool { ); } - RESULT.get_or_init(|| { + let wsl = RESULT.get_or_init(|| { let mut info: libc::utsname = unsafe { mem::zeroed() }; let release: &[u8] = unsafe { libc::uname(&mut info); std::mem::transmute(&info.release[..]) }; + // Sample utsname.release under WSLv2, testing for something like `4.19.104-microsoft-standard` + // or `5.10.16.3-microsoft-standard-WSL2` + if slice_contains_slice(release, b"microsoft-standard") { + return Some(WSL::V2); + } // Sample utsname.release under WSL, testing for something like `4.4.0-17763-Microsoft` if !slice_contains_slice(release, b"Microsoft") { - return false; + return None; } let release: Vec<_> = release @@ -1726,9 +1740,9 @@ pub fn is_windows_subsystem_for_linux() -> bool { .collect(); let build: Result = std::str::from_utf8(&release).unwrap().parse(); match build { - Ok(17763..) => return true, - Ok(_) => (), // return true, but first warn (see below) - _ => return false, // if parsing fails, assume this isn't WSL + Ok(17763..) => return Some(WSL::V1), + Ok(_) => (), // return true, but first warn (see below) + _ => return None, // if parsing fails, assume this isn't WSL }; // #5298, #5661: There are acknowledged, published, and (later) fixed issues with @@ -1752,8 +1766,10 @@ pub fn is_windows_subsystem_for_linux() -> bool { ) ); } - true - }) + Some(WSL::V1) + }); + + wsl.map(|wsl| v == WSL::Any || wsl == v).unwrap_or(false) } /// Return true if the character is in a range reserved for fish's private use. diff --git a/src/input_common.rs b/src/input_common.rs index 8181f5e7c..af3d9bac1 100644 --- a/src/input_common.rs +++ b/src/input_common.rs @@ -1,7 +1,7 @@ use libc::STDOUT_FILENO; use crate::common::{ - fish_reserved_codepoint, is_windows_subsystem_for_linux, read_blocked, shell_modes, + fish_reserved_codepoint, is_windows_subsystem_for_linux, read_blocked, shell_modes, WSL, }; use crate::env::{EnvStack, Environment}; use crate::fd_readable_set::FdReadableSet; @@ -1042,7 +1042,7 @@ pub trait InputEventQueuer { }; // Prevent signal starvation on WSL causing the `torn_escapes.py` test to fail - if is_windows_subsystem_for_linux() { + if is_windows_subsystem_for_linux(WSL::V1) { // Merely querying the current thread's sigmask is sufficient to deliver a pending signal let _ = unsafe { libc::pthread_sigmask(0, ptr::null(), &mut sigs) }; } diff --git a/src/path.rs b/src/path.rs index 81f4d0fe0..7b6771d41 100644 --- a/src/path.rs +++ b/src/path.rs @@ -2,7 +2,7 @@ //! for testing if a command with a given name can be found in the PATH, and various other //! path-related issues. -use crate::common::{is_windows_subsystem_for_linux as is_wsl, wcs2zstring}; +use crate::common::{is_windows_subsystem_for_linux as is_wsl, wcs2zstring, WSL}; use crate::env::{EnvMode, EnvStack, Environment}; use crate::expand::{expand_tilde, HOME_DIRECTORY}; use crate::flog::{FLOG, FLOGF}; @@ -313,7 +313,7 @@ fn path_get_path_core>(cmd: &wstr, pathsv: &[S]) -> GetPathResult // any "normal" nix binaries under these paths, so we can skip them unless we are executing bins // with Windows-ish names. We try to keep paths manually added to $fish_user_paths by only // chopping off entries after the last "normal" PATH entry. - let pathsv = if is_wsl() && !cmd.contains('.') { + let pathsv = if is_wsl(WSL::Any) && !cmd.contains('.') { let win_path_count = pathsv .iter() .rev() diff --git a/src/tests/history.rs b/src/tests/history.rs index f5448b4c9..7169239d6 100644 --- a/src/tests/history.rs +++ b/src/tests/history.rs @@ -1,4 +1,4 @@ -use crate::common::{is_windows_subsystem_for_linux, str2wcstring, wcs2osstring, wcs2string}; +use crate::common::{is_windows_subsystem_for_linux, str2wcstring, wcs2osstring, wcs2string, WSL}; use crate::env::{EnvMode, EnvStack}; use crate::history::{self, History, HistoryItem, HistorySearch, PathList, SearchDirection}; use crate::path::path_get_data; @@ -243,7 +243,7 @@ fn test_history_races_pound_on_history(item_count: usize, idx: usize) { fn test_history_races() { let _cleanup = test_init(); // This always fails under WSL - if is_windows_subsystem_for_linux() { + if is_windows_subsystem_for_linux(WSL::V1) { return; } diff --git a/src/wildcard.rs b/src/wildcard.rs index bf5d68c30..7c72ddaa3 100644 --- a/src/wildcard.rs +++ b/src/wildcard.rs @@ -7,7 +7,7 @@ use std::fs; use crate::common::{ char_offset, is_windows_subsystem_for_linux, unescape_string, UnescapeFlags, - UnescapeStringStyle, WILDCARD_RESERVED_BASE, + UnescapeStringStyle, WILDCARD_RESERVED_BASE, WSL, }; use crate::complete::{CompleteFlags, Completion, CompletionReceiver, PROG_COMPLETE_SEP}; use crate::expand::ExpandFlags; @@ -373,7 +373,7 @@ fn wildcard_test_flags_then_complete( } if executables_only - && is_windows_subsystem_for_linux() + && is_windows_subsystem_for_linux(WSL::Any) && string_suffixes_string_case_insensitive(L!(".dll"), filename) { return false;