Skip to content
Merged
2 changes: 1 addition & 1 deletion src/linux/init/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
22 changes: 19 additions & 3 deletions src/linux/init/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ Return Value:
return SocketFd;
}

int UtilCreateProcessAndWait(const char* const File, const char* const Argv[], int* Status, const std::map<std::string, std::string>& Env)
int UtilCreateProcessAndWait(const char* const File, const char* const Argv[], int* Status, const std::map<std::string, std::string>& Env, bool DetachTerminal)

/*++

Expand All @@ -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.
Expand Down Expand Up @@ -664,7 +667,7 @@ Return Value:

if (UtilSetSignalHandlers(g_SavedSignalActions, false) < 0 || UtilRestoreBlockedSignals() < 0)
{
exit(-1);
_exit(-1);
}

//
Expand All @@ -676,6 +679,19 @@ Return Value:
setenv(e.first.c_str(), e.second.c_str(), 1);
}

//
// Detach from the controlling terminal if requested.
//

if (DetachTerminal)
{
if (setsid() == -1)
{
LOG_ERROR("setsid failed {}", errno);
_exit(-1);
}
}

//
// Invoke the executable.
//
Expand All @@ -686,7 +702,7 @@ Return Value:
// with std::string anyway.
execv(File, const_cast<char* const*>(Argv));
LOG_ERROR("execv({}) failed with {}", File, errno);
exit(-1);
_exit(-1);
}

if (Status == nullptr)
Expand Down
3 changes: 2 additions & 1 deletion src/linux/init/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,8 @@ Return Value:
_exit(1);
}

int UtilCreateProcessAndWait(const char* File, const char* const Argv[], int* Status = nullptr, const std::map<std::string, std::string>& Env = {});
int UtilCreateProcessAndWait(
const char* File, const char* const Argv[], int* Status = nullptr, const std::map<std::string, std::string>& Env = {}, bool DetachTerminal = false);

template <typename TMethod>
void UtilCreateWorkerThread(const char* Name, TMethod&& ThreadFunction)
Expand Down
23 changes: 23 additions & 0 deletions test/windows/UnitTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6539,5 +6539,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"
L"read pass < /dev/tty\n");
VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"chmod +x /sbin/mount.hang"), (DWORD)0);

// 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.
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
Loading