From 994c4c994506389fd3a78ab8fd0a6c131c90f0e7 Mon Sep 17 00:00:00 2001 From: Feng Wang Date: Wed, 18 Mar 2026 15:36:45 +0800 Subject: [PATCH 01/11] detach terminal before running mount -a --- src/linux/init/config.cpp | 2 +- src/linux/init/util.cpp | 14 +++++++++++++- src/linux/init/util.h | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/linux/init/config.cpp b/src/linux/init/config.cpp index 5f6d29db2..b4a554b1c 100644 --- a/src/linux/init/config.cpp +++ b/src/linux/init/config.cpp @@ -2137,7 +2137,7 @@ Return Value: // const char* const Argv[] = {MOUNT_COMMAND, MOUNT_FSTAB_ARG, nullptr}; - if (UtilCreateProcessAndWait(Argv[0], Argv, nullptr, {{WSL_DRVFS_ELEVATED_ENV, Elevated ? "1" : "0"}}) < 0) + if (UtilCreateProcessAndWait(Argv[0], Argv, nullptr, {{WSL_DRVFS_ELEVATED_ENV, Elevated ? "1" : "0"}}, true) < 0) { auto message = wsl::shared::Localization::MessageFstabMountFailed(); LOG_ERROR("{}", message.c_str()); diff --git a/src/linux/init/util.cpp b/src/linux/init/util.cpp index 3cc0ae4c2..907de647a 100644 --- a/src/linux/init/util.cpp +++ b/src/linux/init/util.cpp @@ -613,7 +613,7 @@ Return Value: return SocketFd; } -int UtilCreateProcessAndWait(const char* const File, const char* const Argv[], int* Status, const std::map& Env) +int UtilCreateProcessAndWait(const char* const File, const char* const Argv[], int* Status, const std::map& Env, bool DetachTerminal) /*++ @@ -630,6 +630,9 @@ Routine Description: Status - Supplies an optional pointer that receives the exit status of the process. + DetachTerminal - Supplies a boolean that, when true, calls setsid() in the + child process to detach it from the controlling terminal. + Return Value: 0 on success, -1 on failure. @@ -676,6 +679,15 @@ Return Value: setenv(e.first.c_str(), e.second.c_str(), 1); } + // + // Detach from the controlling terminal if requested. + // + + if (DetachTerminal) + { + setsid(); + } + // // Invoke the executable. // diff --git a/src/linux/init/util.h b/src/linux/init/util.h index 892500b12..da0429d29 100644 --- a/src/linux/init/util.h +++ b/src/linux/init/util.h @@ -191,7 +191,7 @@ Return Value: _exit(1); } -int UtilCreateProcessAndWait(const char* File, const char* const Argv[], int* Status = nullptr, const std::map& Env = {}); +int UtilCreateProcessAndWait(const char* File, const char* const Argv[], int* Status = nullptr, const std::map& Env = {}, bool DetachTerminal = false); template void UtilCreateWorkerThread(const char* Name, TMethod&& ThreadFunction) From b243f0320e86468287c192a2e87828ded7eda1b6 Mon Sep 17 00:00:00 2001 From: Feng Wang Date: Wed, 18 Mar 2026 17:08:11 +0800 Subject: [PATCH 02/11] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/linux/init/util.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/linux/init/util.cpp b/src/linux/init/util.cpp index 907de647a..02dc382b0 100644 --- a/src/linux/init/util.cpp +++ b/src/linux/init/util.cpp @@ -685,7 +685,11 @@ Return Value: if (DetachTerminal) { - setsid(); + if (setsid() == -1) + { + LOG_ERROR("setsid failed {}", errno); + exit(-1); + } } // From 3ab4445e9dad391b85624c04b03abdcd949626dc Mon Sep 17 00:00:00 2001 From: Feng Wang Date: Wed, 18 Mar 2026 17:12:57 +0800 Subject: [PATCH 03/11] use _exit on error before execv in child process to avoid unintentional resource release --- src/linux/init/util.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/linux/init/util.cpp b/src/linux/init/util.cpp index 02dc382b0..c67d69462 100644 --- a/src/linux/init/util.cpp +++ b/src/linux/init/util.cpp @@ -667,7 +667,7 @@ Return Value: if (UtilSetSignalHandlers(g_SavedSignalActions, false) < 0 || UtilRestoreBlockedSignals() < 0) { - exit(-1); + _exit(-1); } // @@ -688,7 +688,7 @@ Return Value: if (setsid() == -1) { LOG_ERROR("setsid failed {}", errno); - exit(-1); + _exit(-1); } } @@ -702,7 +702,7 @@ Return Value: // with std::string anyway. execv(File, const_cast(Argv)); LOG_ERROR("execv({}) failed with {}", File, errno); - exit(-1); + _exit(-1); } if (Status == nullptr) From 83281310249a889f484e6c778e7756eba96f8ed0 Mon Sep 17 00:00:00 2001 From: Feng Wang Date: Thu, 19 Mar 2026 13:49:44 +0800 Subject: [PATCH 04/11] Add regression test --- test/windows/MountTests.cpp | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/test/windows/MountTests.cpp b/test/windows/MountTests.cpp index 00447a062..31a191f1e 100644 --- a/test/windows/MountTests.cpp +++ b/test/windows/MountTests.cpp @@ -1516,5 +1516,40 @@ class MountTests ValidateOffline(false); } } + + TEST_METHOD(TestInteractiveMountDoesNotBlockStartup) + { + WSL2_TEST_ONLY(); + + // Add a fake interactive mount helper. + const std::wstring mountHelper = + L"-- sh -c 'echo \"#!/bin/sh\nread pass < /dev/tty\" > /sbin/mount.hang && chmod +x /sbin/mount.hang'"; + VERIFY_ARE_EQUAL(LxsstuLaunchWsl(mountHelper), (DWORD)0); + + // Add fstab entry using this helper. + const std::wstring addFstab = + L"-- sh -c 'echo \"none /mnt/ttytest hang 0 0\" >> /etc/fstab'"; + VERIFY_ARE_EQUAL(LxsstuLaunchWsl(addFstab), (DWORD)0); + + auto cleanup = wil::scope_exit([&]() { + LxsstuLaunchWsl(L"-- sed -i '/\\/mnt\\/ttytest/d' /etc/fstab"); + LxsstuLaunchWsl(L"-- rm -f /sbin/mount.hang"); + }); + + // Restart the distro with this mount. + WslShutdown(); + + auto cmd = LxssGenerateWslCommandLine(L"echo booted"); + auto process = LxsstuStartProcess(cmd.data()); + auto waitResult = WaitForSingleObject(process.get(), 60 * 1000); + if (waitResult == WAIT_TIMEOUT) + { + TerminateProcess(process.get(), 1); + VERIFY_FAIL(L"WSL startup timed out - fstab mount likely blocked on /dev/tty"); + // Warning: When this error happens, wsl will get stuck in a unrecoverable state. + } + + VERIFY_ARE_EQUAL(waitResult, (DWORD)WAIT_OBJECT_0); + } }; } // namespace MountTests \ No newline at end of file From c2eb91603de44f09e4062deeb7fa4845e53a288c Mon Sep 17 00:00:00 2001 From: Feng Wang Date: Thu, 19 Mar 2026 17:30:31 +0800 Subject: [PATCH 05/11] Fix clang format issue --- test/windows/MountTests.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/windows/MountTests.cpp b/test/windows/MountTests.cpp index 31a191f1e..2c68691e3 100644 --- a/test/windows/MountTests.cpp +++ b/test/windows/MountTests.cpp @@ -1527,8 +1527,7 @@ class MountTests VERIFY_ARE_EQUAL(LxsstuLaunchWsl(mountHelper), (DWORD)0); // Add fstab entry using this helper. - const std::wstring addFstab = - L"-- sh -c 'echo \"none /mnt/ttytest hang 0 0\" >> /etc/fstab'"; + const std::wstring addFstab = L"-- sh -c 'echo \"none /mnt/ttytest hang 0 0\" >> /etc/fstab'"; VERIFY_ARE_EQUAL(LxsstuLaunchWsl(addFstab), (DWORD)0); auto cleanup = wil::scope_exit([&]() { From 790fc0455de9a7475c6fa69d3266de4ccc4f1c59 Mon Sep 17 00:00:00 2001 From: Feng Wang Date: Thu, 19 Mar 2026 17:36:48 +0800 Subject: [PATCH 06/11] fix all clang format issue --- src/linux/init/util.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/linux/init/util.h b/src/linux/init/util.h index da0429d29..1fa5414d5 100644 --- a/src/linux/init/util.h +++ b/src/linux/init/util.h @@ -191,7 +191,8 @@ Return Value: _exit(1); } -int UtilCreateProcessAndWait(const char* File, const char* const Argv[], int* Status = nullptr, const std::map& Env = {}, bool DetachTerminal = false); +int UtilCreateProcessAndWait( + const char* File, const char* const Argv[], int* Status = nullptr, const std::map& Env = {}, bool DetachTerminal = false); template void UtilCreateWorkerThread(const char* Name, TMethod&& ThreadFunction) From d2bfd0b9ff3e6a894637d897d615cbe470622611 Mon Sep 17 00:00:00 2001 From: Feng Wang Date: Thu, 19 Mar 2026 17:38:39 +0800 Subject: [PATCH 07/11] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- test/windows/MountTests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/windows/MountTests.cpp b/test/windows/MountTests.cpp index 2c68691e3..d31a2ec8b 100644 --- a/test/windows/MountTests.cpp +++ b/test/windows/MountTests.cpp @@ -1545,7 +1545,7 @@ class MountTests { TerminateProcess(process.get(), 1); VERIFY_FAIL(L"WSL startup timed out - fstab mount likely blocked on /dev/tty"); - // Warning: When this error happens, wsl will get stuck in a unrecoverable state. + // Warning: When this error happens, wsl will get stuck in an unrecoverable state. } VERIFY_ARE_EQUAL(waitResult, (DWORD)WAIT_OBJECT_0); From 1e5bbb24f0058af113a920e103a63233f9aff1ef Mon Sep 17 00:00:00 2001 From: Feng Wang Date: Thu, 19 Mar 2026 17:48:35 +0800 Subject: [PATCH 08/11] resolve ai comments --- test/windows/MountTests.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/windows/MountTests.cpp b/test/windows/MountTests.cpp index 2c68691e3..2cfd6560b 100644 --- a/test/windows/MountTests.cpp +++ b/test/windows/MountTests.cpp @@ -1523,7 +1523,7 @@ class MountTests // Add a fake interactive mount helper. const std::wstring mountHelper = - L"-- sh -c 'echo \"#!/bin/sh\nread pass < /dev/tty\" > /sbin/mount.hang && chmod +x /sbin/mount.hang'"; + L"-- sh -c 'printf \"#!/bin/sh\\nread pass < /dev/tty\\n\" > /sbin/mount.hang && chmod +x /sbin/mount.hang'"; VERIFY_ARE_EQUAL(LxsstuLaunchWsl(mountHelper), (DWORD)0); // Add fstab entry using this helper. @@ -1544,11 +1544,17 @@ class MountTests if (waitResult == WAIT_TIMEOUT) { TerminateProcess(process.get(), 1); + // WSL is likely stuck; avoid running cleanup that calls LxsstuLaunchWsl again. + cleanup.release(); VERIFY_FAIL(L"WSL startup timed out - fstab mount likely blocked on /dev/tty"); // Warning: When this error happens, wsl will get stuck in a unrecoverable state. } VERIFY_ARE_EQUAL(waitResult, (DWORD)WAIT_OBJECT_0); + + DWORD exitCode = 0; + VERIFY_IS_TRUE(GetExitCodeProcess(process.get(), &exitCode)); + VERIFY_ARE_EQUAL(exitCode, (DWORD)0); } }; } // namespace MountTests \ No newline at end of file From a9c017c14c364441f025a235d59ef0fb87038e38 Mon Sep 17 00:00:00 2001 From: Feng Wang Date: Fri, 20 Mar 2026 11:04:07 +0800 Subject: [PATCH 09/11] move test to unit test --- test/windows/MountTests.cpp | 40 ------------------------------------- test/windows/UnitTests.cpp | 23 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 40 deletions(-) diff --git a/test/windows/MountTests.cpp b/test/windows/MountTests.cpp index eb7c011b3..00447a062 100644 --- a/test/windows/MountTests.cpp +++ b/test/windows/MountTests.cpp @@ -1516,45 +1516,5 @@ class MountTests ValidateOffline(false); } } - - TEST_METHOD(TestInteractiveMountDoesNotBlockStartup) - { - WSL2_TEST_ONLY(); - - // Add a fake interactive mount helper. - const std::wstring mountHelper = - L"-- sh -c 'printf \"#!/bin/sh\\nread pass < /dev/tty\\n\" > /sbin/mount.hang && chmod +x /sbin/mount.hang'"; - VERIFY_ARE_EQUAL(LxsstuLaunchWsl(mountHelper), (DWORD)0); - - // Add fstab entry using this helper. - const std::wstring addFstab = L"-- sh -c 'echo \"none /mnt/ttytest hang 0 0\" >> /etc/fstab'"; - VERIFY_ARE_EQUAL(LxsstuLaunchWsl(addFstab), (DWORD)0); - - auto cleanup = wil::scope_exit([&]() { - LxsstuLaunchWsl(L"-- sed -i '/\\/mnt\\/ttytest/d' /etc/fstab"); - LxsstuLaunchWsl(L"-- rm -f /sbin/mount.hang"); - }); - - // Restart the distro with this mount. - WslShutdown(); - - auto cmd = LxssGenerateWslCommandLine(L"echo booted"); - auto process = LxsstuStartProcess(cmd.data()); - auto waitResult = WaitForSingleObject(process.get(), 60 * 1000); - if (waitResult == WAIT_TIMEOUT) - { - TerminateProcess(process.get(), 1); - // WSL is likely stuck; avoid running cleanup that calls LxsstuLaunchWsl again. - cleanup.release(); - VERIFY_FAIL(L"WSL startup timed out - fstab mount likely blocked on /dev/tty"); - // Warning: When this error happens, wsl will get stuck in an unrecoverable state. - } - - VERIFY_ARE_EQUAL(waitResult, (DWORD)WAIT_OBJECT_0); - - DWORD exitCode = 0; - VERIFY_IS_TRUE(GetExitCodeProcess(process.get(), &exitCode)); - VERIFY_ARE_EQUAL(exitCode, (DWORD)0); - } }; } // namespace MountTests \ No newline at end of file diff --git a/test/windows/UnitTests.cpp b/test/windows/UnitTests.cpp index 8d5e6b39f..4d9ae30f4 100644 --- a/test/windows/UnitTests.cpp +++ b/test/windows/UnitTests.cpp @@ -6538,5 +6538,28 @@ Error code: Wsl/InstallDistro/WSL_E_INVALID_JSON\r\n", VERIFY_ARE_EQUAL(err, L""); } + TEST_METHOD(InteractiveMount) + { + WSL2_TEST_ONLY(); + + // Add a fake interactive mount helper. + DistroFileChange mountHelper(L"/sbin/mount.hang", false); + mountHelper.SetContent( + L"#!/bin/sh\n" + "read pass < /dev/tty\n"); + VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"chmod +x /sbin/mount.hang"), (DWORD)0); + + // Add fstab entry using this helper. + DistroFileChange fstab(L"/etc/fstab"); + fstab.SetContent(L"none /mnt/ttytest hang 0 0\n"); + + // Restart the distro with this mount. + WslShutdown(); + wsl::windows::common::SubProcess process(nullptr, LxssGenerateWslCommandLine(L"echo booted").c_str()); + auto result = process.RunAndCaptureOutput(60 * 1000); + VERIFY_ARE_EQUAL(result.Stdout, L"booted\n"); + VERIFY_ARE_EQUAL(result.ExitCode, 0); + } + }; // namespace UnitTests } // namespace UnitTests From fc75f0153bb1d1db051b2a12afadcf3e6fafee1e Mon Sep 17 00:00:00 2001 From: Feng Wang Date: Fri, 20 Mar 2026 14:14:46 +0800 Subject: [PATCH 10/11] Fix string literal --- test/windows/UnitTests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/windows/UnitTests.cpp b/test/windows/UnitTests.cpp index bb319c097..5a48184f5 100644 --- a/test/windows/UnitTests.cpp +++ b/test/windows/UnitTests.cpp @@ -6547,7 +6547,7 @@ Error code: Wsl/InstallDistro/WSL_E_INVALID_JSON\r\n", DistroFileChange mountHelper(L"/sbin/mount.hang", false); mountHelper.SetContent( L"#!/bin/sh\n" - "read pass < /dev/tty\n"); + L"read pass < /dev/tty\n"); VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"chmod +x /sbin/mount.hang"), (DWORD)0); // Add fstab entry using this helper. From 4bb98a0e13029a5d1a45d039146a28378086d3bf Mon Sep 17 00:00:00 2001 From: Feng Wang Date: Fri, 20 Mar 2026 18:09:49 +0800 Subject: [PATCH 11/11] Overwrite fstab to resolve pipeline missing file issue --- test/windows/UnitTests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/windows/UnitTests.cpp b/test/windows/UnitTests.cpp index 5a48184f5..f97e96455 100644 --- a/test/windows/UnitTests.cpp +++ b/test/windows/UnitTests.cpp @@ -6550,8 +6550,8 @@ Error code: Wsl/InstallDistro/WSL_E_INVALID_JSON\r\n", L"read pass < /dev/tty\n"); VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"chmod +x /sbin/mount.hang"), (DWORD)0); - // Add fstab entry using this helper. - DistroFileChange fstab(L"/etc/fstab"); + // Don't keep the original fstab as it can be missing on the pipeline. + DistroFileChange fstab(L"/etc/fstab", false); fstab.SetContent(L"none /mnt/ttytest hang 0 0\n"); // Restart the distro with this mount.