Skip daemon auto-start for Windows-mounted WSL homes (#50555)

## Why

The managed daemon writes an executable and Unix-style state beneath `CODEX_HOME`. Windows-mounted WSL filesystems (DrvFS/9p) do not reliably support the required permission semantics, which can cause startup to fail before the TUI opens.

## What changed

Detect WSL homes on 9p filesystems, checking an existing ancestor when `CODEX_HOME` does not yet exist. Keep the TUI in embedded mode instead of automatically starting the shared background server, and show a startup warning explaining the exclusion.

## Testing

Extend the daemon exclusion warning snapshot to cover the Windows-mounted WSL message.

GitOrigin-RevId: 995e6236d79d8190b0ab1e6b4761eeef3c068467
This commit is contained in:
Eric Traut
2026-10-03 07:05:36 +00:00
committed by copyberry
parent 55b6f282a8
commit 6b43e6fe1f
4 changed files with 44 additions and 0 deletions
+31
View File
@@ -15,6 +15,37 @@ const SERVER_FEATURES: [Feature; 4] = [
];
pub(super) const FAILURE_HINT: &str = "To work without the background server, rerun the same command with --no-daemon (including resume or fork and its arguments).";
pub(super) const WSL_DRVFS_EXCLUSION: &str = "a Windows-mounted WSL CODEX_HOME (DrvFS/9p)";
pub(super) fn uses_wsl_drvfs(codex_home: &std::path::Path) -> bool {
// The managed daemon writes an executable and Unix-style state beneath CODEX_HOME.
// DrvFS does not reliably support the required permission semantics, so starting it
// there can fail before the TUI opens.
#[cfg(target_os = "linux")]
{
use std::os::fd::AsRawFd;
if !codex_utils_path::is_wsl() && std::env::var_os("WSL_INTEROP").is_none() {
return false;
}
let Some(directory) = codex_home
.ancestors()
.find_map(|path| std::fs::File::open(path).ok())
else {
return false;
};
let mut stats = std::mem::MaybeUninit::<libc::statfs>::uninit();
if unsafe { libc::fstatfs(directory.as_raw_fd(), stats.as_mut_ptr()) } != 0 {
return false;
}
unsafe { stats.assume_init() }.f_type as u64 == 0x0102_1997
}
#[cfg(not(target_os = "linux"))]
{
let _ = codex_home;
false
}
}
#[cfg(any(windows, test))]
pub(super) const ELEVATED_LAUNCH_WARNING: &str = "Running as administrator: shared background server disabled. To enable it, restart Codex in a terminal without administrator permissions.";
+4
View File
@@ -431,6 +431,10 @@ fn daemon_exclusion_warning_snapshot() {
let cell = crate::history_cell::StartupWarningsCell::new(vec![
"Running without the shared background server: --strict-config requires embedded mode."
.into(),
format!(
"Running without the shared background server: {} requires embedded mode.",
daemon_startup::WSL_DRVFS_EXCLUSION
),
]);
let text = cell
.transcript_lines(/*width*/ 80)
@@ -4,3 +4,5 @@ expression: text
---
⚠ Running without the shared background server: --strict-config requires
embedded mode.
⚠ Running without the shared background server: a Windows-mounted WSL CODEX_HOME
(DrvFS/9p) requires embedded mode.
@@ -533,6 +533,13 @@ pub(super) async fn run_main_inner(
daemon_exclusion = Some("Bedrock sign-in");
app_server_target = AppServerTarget::Embedded;
}
if auto_start_daemon
&& daemon_exclusion.is_none()
&& matches!(&app_server_target, AppServerTarget::Embedded)
&& daemon_startup::uses_wsl_drvfs(&codex_home)
{
daemon_exclusion = Some(daemon_startup::WSL_DRVFS_EXCLUSION);
}
let mut daemon_features = daemon_startup::server_features(&cli_kv_overrides);
// Disabling shared services requires confirmation, even on a fresh auto-start.
daemon_features.retain(|_, enabled| *enabled);