Skip to content

Conversation

@OneBlue
Copy link
Collaborator

@OneBlue OneBlue commented Dec 2, 2025

Summary of the Pull Request

** This change depends on: #13791 **

This change refactors the session creation logic to:

  • Make the storage disk creation easier
  • Get rid of the old VM settings
  • Run the init script from within the service
  • Simplify testing

After this change, running wsl --wsla will open a shell in a VM already configured to run nerdctl. --storage can be passed to enable on disk storage, otherwise a tmpfs will be used to allow container creation.

PR Checklist

  • Closes: Link to issue #xxx
  • Communication: I've discussed this with core contributors already. If work hasn't been agreed, this work might be rejected
  • Tests: Added/updated if needed and all pass
  • Localization: All end user facing strings can be localized
  • Dev docs: Added/updated if needed
  • Documentation updated: If checked, please file a pull request on our docs repo and link it here: #xxx

Detailed Description of the Pull Request / Additional comments

Validation Steps Performed

@OneBlue OneBlue requested a review from a team as a code owner December 2, 2025 02:37
Copilot AI review requested due to automatic review settings December 2, 2025 02:37
@OneBlue OneBlue changed the base branch from master to feature/wsl-for-apps December 2, 2025 02:37
@OneBlue OneBlue requested a review from a team as a code owner December 2, 2025 02:37
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request refactors the WSLA (Windows Subsystem for Linux API) session creation logic to simplify storage disk management, remove deprecated VM settings, integrate init script execution into the service, and introduce container support via nerdctl.

Key Changes:

  • Consolidated session settings by removing VIRTUAL_MACHINE_SETTINGS structure and moving relevant fields into WSLA_SESSION_SETTINGS
  • Added container creation capabilities through new WSLAContainer and WSLAContainerLauncher classes
  • Fixed critical inverted state validation logic in VM operations (AttachDisk, Fork, Shutdown, Signal)
  • Introduced storage VHD management with automatic creation and formatting
  • Switched test environment from full Linux distributions to busybox-based minimal rootfs

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 18 comments.

Show a summary per file
File Description
src/windows/wslaservice/inc/wslaservice.idl Removed VIRTUAL_MACHINE_SETTINGS; consolidated into WSLA_SESSION_SETTINGS; added WSLAFeatureFlags enum; changed WSLA_PROCESS_OPTIONS.Executable to [unique]; added OpenSessionByName method
test/windows/WSLATests.cpp Updated all tests to use new session settings API; changed shell from /bin/bash to /bin/sh for busybox compatibility; added CreateContainer test; created GetDefaultSessionSettings() helper
src/windows/wslaservice/exe/WSLAVirtualMachine.h Introduced Settings struct to replace VIRTUAL_MACHINE_SETTINGS; removed GetDebugShellPipe method; added Mount public method
src/windows/wslaservice/exe/WSLAVirtualMachine.cpp Fixed inverted m_running validation bugs; removed debug shell pipe support; moved DmesgHandle from ULONG to wil::unique_handle; added FeatureEnabled helper
src/windows/wslaservice/exe/WSLAUserSession.h/cpp Updated CreateSession to accept only WSLA_SESSION_SETTINGS; added OpenSessionByName implementation
src/windows/wslaservice/exe/WSLASession.h/cpp Refactored to create VM settings from session settings; added ConfigureStorage for automatic VHD creation/formatting; integrated init script execution
src/windows/wslaservice/exe/WSLAProcess.cpp Added m_exitEvent.SetEvent() call in OnVmTerminated for proper cleanup
src/windows/wslaservice/exe/WSLAContainer.h/cpp Implemented container creation via nerdctl with support for basic options (image, name, entrypoint, environment, stdin/tty handling)
src/windows/common/WSLAContainerLauncher.h/cpp New client-side wrapper for launching containers through the WSLA API
src/windows/common/WSLAProcessLauncher.h/cpp Added DEFAULT_MOVABLE macro usage for move semantics support
src/windows/common/WslCoreFilesystem.cpp Changed VHD extension validation from WI_ASSERT to THROW_HR_IF for production safety
src/windows/common/WslClient.cpp Updated WslaShell debug tool to use new session settings; added container launch support
src/shared/inc/defs.h Added DEFAULT_MOVABLE macro for default move constructor/assignment
CMakeLists.txt Fixed CMake conditional from DEFINED check to boolean check
msipackage/package.wix.in Added wslarootfs.vhd to installer for x64 builds

Comment on lines +74 to +77
THROW_HR_IF(E_INVALIDARG, Settings.RootVhdTypeOverride == nullptr);

vmSettings.RootVhd = Settings.RootVhdOverride;
vmSettings.RootVhdType = Settings.RootVhdTypeOverride;
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The error condition checks if RootVhdTypeOverride is null when RootVhdOverride is not null. However, there's an asymmetry: when RootVhdOverride is null (line 81-83), a default VHD type of "squashfs" is used. Consider also providing a sensible default for RootVhdTypeOverride (e.g., "ext4") instead of requiring it to be specified, or document why it must be explicitly provided.

Suggested change
THROW_HR_IF(E_INVALIDARG, Settings.RootVhdTypeOverride == nullptr);
vmSettings.RootVhd = Settings.RootVhdOverride;
vmSettings.RootVhdType = Settings.RootVhdTypeOverride;
vmSettings.RootVhd = Settings.RootVhdOverride;
vmSettings.RootVhdType = Settings.RootVhdTypeOverride != nullptr ? Settings.RootVhdTypeOverride : "ext4";

Copilot uses AI. Check for mistakes.

// Note: fd/0 is opened by readlink to read the actual content of /proc/self/fd.
if (!PathMatchSpecA(result.Output[1].c_str(), "/proc/self/fd/0 /proc/self/fd/1 /proc/self/fd/2\nsocket:[*]\nsocket:[*]\n"))
if (!PathMatchSpecA(result.Output[1].c_str(), "/proc/self/fd/0 /proc/self/fd/1 /proc/self/fd/2\n"))
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test expectation changed to no longer expect socket file descriptors in the output (removed socket:[*]\nsocket:[*]\n). This suggests a behavioral change where processes no longer have extra socket file descriptors open. Verify this is intentional and doesn't indicate a regression in socket handling or file descriptor management.

Copilot uses AI. Check for mistakes.
CMakeLists.txt Outdated
endif()

if (NOT DEFINED OFFICIAL_BUILD AND ${TARGET_PLATFORM} STREQUAL "x64")
if (NOT OFFICIAL_BUILD AND ${TARGET_PLATFORM} STREQUAL "x64")
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition should use && (logical AND) instead of AND (which is not standard C++). While some compilers may define AND as a macro or alternative token, it's better to use the standard && operator for portability and clarity.

Copilot uses AI. Check for mistakes.
};

struct WSLA_PROCESS_OPTIONS
{
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The [unique] attribute on Executable was added, but this could be a breaking API change. If existing callers pass a non-null Executable, this change should be safe. However, if the intention is to allow null executables (as suggested by the container launcher code), ensure all consumers handle this correctly. The container code at line 142-146 in WSLAContainer.cpp explicitly handles null executables, which is good.

Suggested change
{
{
// May be NULL. Consumers must handle the case where Executable is not provided.

Copilot uses AI. Check for mistakes.
LPCSTR Image;
LPCSTR Name;
struct WSLA_PROCESS_OPTIONS* InitProcessOptions;
struct WSLA_PROCESS_OPTIONS InitProcessOptions;
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The field changed from a pointer (struct WSLA_PROCESS_OPTIONS*) to a value type (struct WSLA_PROCESS_OPTIONS). This is a breaking API change. Ensure all callers have been updated to pass the structure by value instead of by pointer.

Copilot uses AI. Check for mistakes.
THROW_HR_IF_MSG(
E_INVALIDARG,
options.InitProcessOptions.Environment[i][0] == L'-',
"Invlaid environment string: %hs",
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in error message: "Invlaid" should be "Invalid".

Suggested change
"Invlaid environment string: %hs",
"Invalid environment string: %hs",

Copilot uses AI. Check for mistakes.
THROW_HR_IF_MSG(
E_INVALIDARG,
options.InitProcessOptions.Environment[i][0] == L'-',
"Invlaid environment string: %hs",
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The environment validation checks if the string starts with - but uses the wrong error message format specifier. The parameter options.InitProcessOptions.Environment[i] is declared as LPCSTR* (array of char pointers), so individual elements are LPCSTR (char*). However, the error message uses %hs which expects a char*, but this should work. The real issue is the error message says "Invlaid" (typo already noted) and "environment string" when it's checking for a dash prefix, which typically indicates an argument flag confusion. Consider clarifying the error message to explain why a dash prefix is invalid (e.g., "Environment variable must not start with '-'").

Suggested change
"Invlaid environment string: %hs",
"Invalid environment variable: %hs. Environment variable must not start with '-'",

Copilot uses AI. Check for mistakes.
This file contains the definition for WSLAContainerLauncher.
--*/
#include "WSLAprocessLauncher.h"
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent casing in include: should be "WSLAProcessLauncher.h" (capital P) to match the actual filename based on other includes in the codebase.

Suggested change
#include "WSLAprocessLauncher.h"
#include "WSLAProcessLauncher.h"

Copilot uses AI. Check for mistakes.
if (result.Code != expectedResult)
{
LogError(
"Comman didn't return expected code (%i). ExitCode: %i, Stdout: '%hs', Stderr: '%hs'",
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in error message: "Comman" should be "Command".

Suggested change
"Comman didn't return expected code (%i). ExitCode: %i, Stdout: '%hs', Stderr: '%hs'",
"Command didn't return expected code (%i). ExitCode: %i, Stdout: '%hs', Stderr: '%hs'",

Copilot uses AI. Check for mistakes.
"Failed to attach vhd: %ls",
m_storageVhdPath.c_str());

// If the VHD wasn'found, create it.
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in comment: "wasn'found" should be "wasn't found".

Suggested change
// If the VHD wasn'found, create it.
// If the VHD wasn't found, create it.

Copilot uses AI. Check for mistakes.
@OneBlue OneBlue changed the title User/oneblue/container api update Refactor the session creation logic to match the new API Dec 2, 2025
{
THROW_HR_IF_MSG(
result,
result != HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) && result != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are we ignoring these failures?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, still seems odd to try to attach a disk that doesn't exist.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about that vs explicitly checking if the file exists, my thinking was that they're equivalent, but in the case where the VHD does exists, this approach allows us to avoid a file access to validate that the VHD exists

Comment on lines 203 to 205
if (m_settings.DmesgHandle)
{
dmesgOutput.reset(wsl::windows::common::wslutil::DuplicateHandleFromCallingProcess(ULongToHandle(m_settings.DmesgOutput)));
dmesgOutput = std::move(m_settings.DmesgHandle);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this whole condition be removed and just always move the dmesg handle? won't harm anythigng if it's empty.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, it can

WSL_LOG("CreateWSLAVirtualMachine", TraceLoggingValue(json.c_str(), "json"));

m_computeSystem = hcs::CreateComputeSystem(m_vmIdString.c_str(), json.c_str());
m_running = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Running is a poor name since the VM has not started yet.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it belong after StartComputeSystem?

(200+ line function, phew :) )

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed. Moved after StartComputeSystem

WSL_LOG("CreateWSLAVirtualMachine", TraceLoggingValue(json.c_str(), "json"));

m_computeSystem = hcs::CreateComputeSystem(m_vmIdString.c_str(), json.c_str());
m_running = true;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it belong after StartComputeSystem?

(200+ line function, phew :) )

@OneBlue OneBlue enabled auto-merge (squash) December 4, 2025 01:38
@OneBlue OneBlue merged commit 844acd0 into feature/wsl-for-apps Dec 4, 2025
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants