Merge merge into feature/wsl-for-apps

This commit is contained in:
Blue 2025-10-20 12:40:02 -07:00
parent f2bd6d60bc
commit 9d505519ea
48 changed files with 954 additions and 399 deletions

View File

@ -34,8 +34,8 @@ FetchContent_GetProperties(GSL SOURCE_DIR GSL_SOURCE_DIR)
FetchContent_Declare(nlohmannjson FetchContent_Declare(nlohmannjson
URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz URL https://github.com/nlohmann/json/releases/download/v3.12.0/json.tar.xz
URL_HASH SHA256=d6c65aca6b1ed68e7a182f4757257b107ae403032760ed6ef121c9d55e81757d) URL_HASH SHA256=42f6e95cad6ec532fd372391373363b62a14af6d771056dbfc86160e6dfff7aa )
FetchContent_MakeAvailable(nlohmannjson) FetchContent_MakeAvailable(nlohmannjson)
FetchContent_GetProperties(nlohmannjson SOURCE_DIR NLOHMAN_JSON_SOURCE_DIR) FetchContent_GetProperties(nlohmannjson SOURCE_DIR NLOHMAN_JSON_SOURCE_DIR)

View File

@ -1762,192 +1762,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
---------------------------------------------------------
---------------------------------------------------------
Microsoft.NETCore.App.Runtime.win-arm64 9.0.8 - MIT
Copyright (c) 2021
Copyright (c) Six Labors
(c) Microsoft Corporation
Copyright (c) 2022 FormatJS
Copyright (c) Andrew Arnott
Copyright 2019 LLVM Project
Copyright (c) 1998 Microsoft
Copyright 2018 Daniel Lemire
Copyright (c) .NET Foundation
Copyright 1995-2022 Mark Adler
Copyright 1995-2024 Mark Adler
Copyright (c) 2011, Google Inc.
Copyright (c) 2020 Dan Shechter
(c) 1997-2005 Sean Eron Anderson
Copyright (c) 2015 Andrew Gallant
Copyright (c) 2022, Wojciech Mula
Copyright (c) 2017 Yoshifumi Kawai
Copyright (c) 2022, Geoff Langdale
Copyright (c) 2005-2020 Rich Felker
Copyright (c) 2012-2021 Yann Collet
Copyright (c) Microsoft Corporation
Copyright (c) 2007 James Newton-King
Copyright (c) 1991-2022 Unicode, Inc.
Copyright (c) 2013-2017, Alfred Klomp
Copyright (c) 2018 Nemanja Mijailovic
Copyright 2012 the V8 project authors
Copyright (c) 1999 Lucent Technologies
Copyright (c) 2008-2016, Wojciech Mula
Copyright (c) 2011-2020 Microsoft Corp
Copyright (c) 2015-2017, Wojciech Mula
Copyright (c) 2015-2018, Wojciech Mula
Copyright (c) 2005-2007, Nick Galbreath
Copyright (c) 2015 The Chromium Authors
Copyright (c) 2018 Alexander Chermyanin
Copyright (c) The Internet Society 1997
Copyright (c) 2004-2006 Intel Corporation
Copyright (c) 2011-2015 Intel Corporation
Copyright (c) 2013-2017, Milosz Krajewski
Copyright (c) 2016-2017, Matthieu Darbois
Copyright (c) The Internet Society (2003)
Copyright (c) .NET Foundation Contributors
(c) 1995-2024 Jean-loup Gailly and Mark Adler
Copyright (c) 2020 Mara Bos <m-ou.se@m-ou.se>
Copyright (c) .NET Foundation and Contributors
Copyright (c) 2012 - present, Victor Zverovich
Copyright (c) 2006 Jb Evain (jbevain@gmail.com)
Copyright (c) 2008-2020 Advanced Micro Devices, Inc.
Copyright (c) 2019 Microsoft Corporation, Daan Leijen
Copyright (c) 2011 Novell, Inc (http://www.novell.com)
Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com)
Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors
Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com
Copyright 1995-2024 Jean-loup Gailly and Mark Adler Qkkbal
Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc.
Portions (c) International Organization for Standardization 1986
Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang) Disclaimers
Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip
Copyright (c) 1980, 1986, 1993 The Regents of the University of California
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California
Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass
The MIT License (MIT)
Copyright (c) .NET Foundation and Contributors
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
---------------------------------------------------------
---------------------------------------------------------
Microsoft.NETCore.App.Runtime.win-x64 9.0.8 - MIT
Copyright (c) 2021
Copyright (c) Six Labors
(c) Microsoft Corporation
Copyright (c) 2022 FormatJS
Copyright (c) Andrew Arnott
Copyright 2019 LLVM Project
Copyright (c) 1998 Microsoft
Copyright 2018 Daniel Lemire
Copyright (c) .NET Foundation
Copyright 1995-2022 Mark Adler
Copyright 1995-2024 Mark Adler
Copyright (c) 2011, Google Inc.
Copyright (c) 2020 Dan Shechter
(c) 1997-2005 Sean Eron Anderson
Copyright (c) 2015 Andrew Gallant
Copyright (c) 2022, Wojciech Mula
Copyright (c) 2017 Yoshifumi Kawai
Copyright (c) 2022, Geoff Langdale
Copyright (c) 2005-2020 Rich Felker
Copyright (c) 2012-2021 Yann Collet
Copyright (c) Microsoft Corporation
Copyright (c) 2007 James Newton-King
Copyright (c) 1991-2022 Unicode, Inc.
Copyright (c) 2013-2017, Alfred Klomp
Copyright (c) 2018 Nemanja Mijailovic
Copyright 2012 the V8 project authors
Copyright (c) 1999 Lucent Technologies
Copyright (c) 2008-2016, Wojciech Mula
Copyright (c) 2011-2020 Microsoft Corp
Copyright (c) 2015-2017, Wojciech Mula
Copyright (c) 2015-2018, Wojciech Mula
Copyright (c) 2005-2007, Nick Galbreath
Copyright (c) 2015 The Chromium Authors
Copyright (c) 2018 Alexander Chermyanin
Copyright (c) The Internet Society 1997
Copyright (c) 2004-2006 Intel Corporation
Copyright (c) 2011-2015 Intel Corporation
Copyright (c) 2013-2017, Milosz Krajewski
Copyright (c) 2016-2017, Matthieu Darbois
Copyright (c) The Internet Society (2003)
Copyright (c) .NET Foundation Contributors
(c) 1995-2024 Jean-loup Gailly and Mark Adler
Copyright (c) 2020 Mara Bos <m-ou.se@m-ou.se>
Copyright (c) .NET Foundation and Contributors
Copyright (c) 2012 - present, Victor Zverovich
Copyright (c) 2006 Jb Evain (jbevain@gmail.com)
Copyright (c) 2008-2020 Advanced Micro Devices, Inc.
Copyright (c) 2019 Microsoft Corporation, Daan Leijen
Copyright (c) 2011 Novell, Inc (http://www.novell.com)
Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com)
Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors
Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com
Copyright 1995-2024 Jean-loup Gailly and Mark Adler Qkkbal
Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc.
Portions (c) International Organization for Standardization 1986
Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang) Disclaimers
Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip
Copyright (c) 1980, 1986, 1993 The Regents of the University of California
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California
Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass
The MIT License (MIT)
Copyright (c) .NET Foundation and Contributors
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--------------------------------------------------------- ---------------------------------------------------------
--------------------------------------------------------- ---------------------------------------------------------

View File

@ -21,6 +21,10 @@ if ($LogProfile -eq $null -Or ![System.IO.File]::Exists($LogProfile))
{ {
$url = "https://raw.githubusercontent.com/microsoft/WSL/master/diagnostics/wsl_storage.wprp" $url = "https://raw.githubusercontent.com/microsoft/WSL/master/diagnostics/wsl_storage.wprp"
} }
elseif ($LogProfile -eq "hvsocket")
{
$url = "https://raw.githubusercontent.com/microsoft/WSL/master/diagnostics/wsl_hvsocket.wprp"
}
else else
{ {
Write-Error "Unknown log profile: $LogProfile" Write-Error "Unknown log profile: $LogProfile"
@ -52,6 +56,8 @@ if (Test-Path $wslconfig)
Copy-Item $wslconfig $folder | Out-Null Copy-Item $wslconfig $folder | Out-Null
} }
Copy-Item "C:\Windows\temp\wsl-install-log.txt" $folder -ErrorAction ignore
get-appxpackage MicrosoftCorporationII.WindowsSubsystemforLinux -ErrorAction Ignore > $folder/appxpackage.txt get-appxpackage MicrosoftCorporationII.WindowsSubsystemforLinux -ErrorAction Ignore > $folder/appxpackage.txt
get-acl "C:\ProgramData\Microsoft\Windows\WindowsApps" -ErrorAction Ignore | Format-List > $folder/acl.txt get-acl "C:\ProgramData\Microsoft\Windows\WindowsApps" -ErrorAction Ignore | Format-List > $folder/acl.txt
Get-WindowsOptionalFeature -Online > $folder/optional-components.txt Get-WindowsOptionalFeature -Online > $folder/optional-components.txt

View File

@ -0,0 +1,172 @@
<?xml version="1.0"?>
<WindowsPerformanceRecorder Version="1">
<Profiles>
<EventCollector Id="Collector" Name="Collector">
<BufferSize Value="512" />
<Buffers Value="10" PercentageOfTotalMemory="true"/>
</EventCollector>
<EventProvider Id="EventProvider_HvSocketTraceProvider" Name="B2ED3BDB-CD74-5B2C-F660-85079CA074B3" NonPagedMemory="true">
<Keywords>
<Keyword Value="0x0"/>
</Keywords>
</EventProvider>
<EventProvider Id="lxcore_kernel" Name="0CD1C309-0878-4515-83DB-749843B3F5C9"/>
<EventProvider Id="lxcore_user" Name="D90B9468-67F0-5B3B-42CC-82AC81FFD960"/>
<EventProvider Id="lxcore_service" Name="B99CDB5A-039C-5046-E672-1A0DE0A40211"/>
<EventProvider Id="wsl_devicehost" Name="9d6c7b9e-2581-4d8a-b8c5-b90b4a17094a"/>
<EventProvider Id="wslclient" Name="8cbb7724-7223-5d6f-8137-564dac45104d"/>
<EventProvider Id="wslapi" Name="beb94edf-1a7b-5058-0696-ff9e6b1798d1"/>
<EventProvider Id="vm_chipset" Name="de9ba731-7f33-4f44-98c9-6cac856b9f83"/>
<EventProvider Id="vmcompute_dll" Name="AF7FD3A7-B248-460C-A9F5-FEC39EF8468C"/>
<EventProvider Id="vmcompute" Name="17103E3F-3C6E-4677-BB17-3B267EB5BE57"/>
<EventProvider Id="vmmm" Name="6066F867-7CA1-4418-85FD-36E3F9C0600C"/>
<EventProvider Id="vmwp" Name="51DDFA29-D5C8-4803-BE4B-2ECB715570FE"/>
<EventProvider Id="9p" Name="e13c8d52-b153-571f-78c5-1d4098af2a1e"/>
<EventProvider Id="9p_errors" Name="06C601B3-6957-4F8C-A15F-74875B24429D" />
<EventProvider Id="p9rdr" Name="bb1d36f0-e0e0-48cc-9493-fef0e3d0b28c" />
<EventProvider Id="mup" Name="20c46239-d059-4214-a11e-7d6769cbe020" />
<EventProvider Id="rfsmon" Name="51734B23-5B7E-4892-BA8E-45BC110B735C" />
<EventProvider Id="hyperv_storage" Name="c7ad62c6-5c99-5a1b-bbc4-0821ae5b765e" />
<EventProvider Id="hns" Name="0c885e0d-6eb6-476c-a048-2457eed3a5c1" />
<EventProvider Id="netmgmt" Name="93f693dc-9163-4dee-af64-d855218af242" />
<EventProvider Id="EventProvider_Microsoft.Windows.Mobile.Provisioning.AppDownload" Name="0BBE6221-EF09-4A3F-82EE-BE00DBB6A98A" />
<EventProvider Id="EventProvider_Microsoft.Windows.Mobile.Provisioning.Datastore" Name="42C60CEA-0FE7-4541-A86B-9E11F95BD9BF" />
<EventProvider Id="EventProvider_Microsoft.Windows.Mobile.Provisioning.PhoneProvisioner" Name="B876B1FC-C7F1-443E-9012-86677F7DE580" />
<EventProvider Id="EventProvider_Microsoft.Windows.Mobile.Provisioning.PPOEM" Name="7EDBED09-1FF7-4FEE-B8C3-5DB694420830" />
<EventProvider Id="EventProvider_Microsoft.Windows.Provisioning.API" Name="82ADD491-01D7-4B85-9EAD-192C3CAACA23" />
<EventProvider Id="EventProvider_Microsoft.Windows.Provisioning.CSP" Name="16E12400-A2D8-44B7-9479-004568EC7819" />
<EventProvider Id="EventProvider_Microsoft.Windows.Provisioning.Engine" Name="A6A847B7-4429-49AA-BBA6-2AD8C191AC8C" />
<EventProvider Id="EventProvider_Microsoft.Windows.Provisioning.Handlers" Name="0383D92C-2337-4F25-A0B5-A51767F04746" />
<EventProvider Id="EventProvider_Microsoft.Windows.Provisioning.Migration" Name="A0AF985E-83F9-4E1A-B658-338DCFE27893" />
<EventProvider Id="EventProvider_Microsoft.Windows.Provisioning.Operations" Name="7F99598F-B2C1-4371-9911-63DEE13B9EB1" />
<EventProvider Id="EventProvider_Microsoft.Windows.Provisioning.Platform" Name="B1F30020-8BC3-4888-BB1B-4DD681F24209" />
<EventProvider Id="EventProvider_Microsoft.Windows.Provisioning.Plugin.Engine" Name="55239D60-0EB6-495B-874E-15DE5D5F9A70" />
<EventProvider Id="EventProvider_Microsoft.Windows.Provisioning.Plugin.RemovableMedia" Name="B55883E6-6C45-45C2-AB9D-800BB7B66B13" />
<EventProvider Id="EventProvider_Microsoft.Windows.Provisioning.ProvTool" Name="2BF4B6BA-556E-4D05-8534-CAFEDF19FED8" />
<EventProvider Id="EventProvider_Microsoft.Windows.Provisioning.CommandCsp" Name="00BB69FC-60BC-4502-9438-25608F375CCB" />
<EventProvider Id="EventProvider_Microsoft.Windows.Provisioning.ProvLaunch" Name="08FACCFA-125D-4ED6-B0B7-B4A1A912E693" />
<EventProvider Id="EventProvider_Microsoft.Windows.EMPS.Enrollment" Name="E74EFD1A-B62D-4B83-AB00-66F4A166A2D3" />
<EventProvider Id="EventProvider_Microsoft.Windows.EnterpriseManagement.Enrollment" Name="F9E3B648-9AF1-4DC3-9A8E-BF42C0FBCE9A" />
<EventProvider Id="Microsoft.Windows.HyperV.Vid" Name="1111450B-DACC-40A3-84AB-F7DBA4A6E63A" NonPagedMemory="true"/>
<EventProvider Id="Microsoft-Windows-HyperV-Vid" Name="5931D877-4860-4ee7-A95C-610A5F0D1407" NonPagedMemory="true" />
<EventProvider Id="virtdisk_wpp" Name="e14dcdd9-d1ec-4dc3-8395-a606df8ef115" Level="4">
<Keywords>
<Keyword Value="0xFFFFFFFFFFFFFFFF" />
</Keywords>
</EventProvider>
<EventProvider Id="virtdisk" Name="4D20DF22-E177-4514-A369-F1759FEEDEB3" Level="4">
<Keywords>
<Keyword Value="0xFFFFFFFFFFFFFFFF" />
</Keywords>
</EventProvider>
<EventProvider Id="vhdmp" Name="E2816346-87F4-4F85-95C3-0C79409AA89D" NonPagedMemory="true" Level="4">
<Keywords>
<Keyword Value="0xFFFFFFFFFFFFFFFD" />
</Keywords>
</EventProvider>
<EventProvider Id="vhdmp_wpp" Name="3c70c3b0-2fae-41d3-b68d-8f7fcaf79adb" NonPagedMemory="true" Level="5">
<Keywords>
<Keyword Value="0xFFFFFFFFFFFFFFFF" />
</Keywords>
</EventProvider>
<EventProvider Id="storvsp" Name="10b3d268-9782-49a4-aacc-a93c5482cb6f" NonPagedMemory="true" Level="4">
<Keywords>
<Keyword Value="0xFFFFFFFFFFFFFFFF" />
</Keywords>
</EventProvider>
<EventProvider Id="HyperV_SyntheticStorage" Name="EDACD782-2564-4497-ADE6-7199377850F2" Level="6">
<Keywords>
<Keyword Value="0xFFFFFFFFFFFFFFFF" />
</Keywords>
</EventProvider>
<EventProvider Id="HyperV_EmulatedStorage" Name="86E15E01-EDF1-4AC7-89CF-B19563FD6894" Level="6">
<Keywords>
<Keyword Value="0xFFFFFFFFFFFFFFFF" />
</Keywords>
</EventProvider>
<EventProvider Id="EventProvider_Telemetry_StorVSP" Name="544d0787-9f6d-432e-8414-e035a8b0541d">
<Keywords>
<Keyword Value="0xFFFFFFFFFFFFFFFF" />
</Keywords>
</EventProvider>
<EventProvider Id="EventProvider_Trace_Vhdmp" Name="dc284fb3-1eab-4854-828a-b25417280280" Level="3">
<Keywords>
<Keyword Value="0xFFFFFFFFFFFFFFFF" />
</Keywords>
</EventProvider>
<Profile
Id="WSL.Verbose.File"
Name="WSL"
Description="Traces for all WSL components"
LoggingMode="File"
DetailLevel="Verbose"
>
<Collectors>
<EventCollectorId Value="Collector">
<EventProviders>
<EventProviderId Value="lxcore_kernel"/>
<EventProviderId Value="lxcore_user"/>
<EventProviderId Value="lxcore_service"/>
<EventProviderId Value="wsl_devicehost"/>
<EventProviderId Value="wslclient"/>
<EventProviderId Value="wslapi"/>
<EventProviderId Value="vm_chipset"/>
<EventProviderId Value="vmcompute_dll"/>
<EventProviderId Value="vmcompute"/>
<EventProviderId Value="vmmm"/>
<EventProviderId Value="vmwp"/>
<EventProviderId Value="9p"/>
<EventProviderId Value="9p_errors"/>
<EventProviderId Value="p9rdr"/>
<EventProviderId Value="mup"/>
<EventProviderId Value="rfsmon"/>
<EventProviderId Value="hyperv_storage"/>
<EventProviderId Value="hns"/>
<EventProviderId Value="netmgmt"/>
<EventProviderId Value="EventProvider_Microsoft.Windows.Mobile.Provisioning.AppDownload"/>
<EventProviderId Value="EventProvider_Microsoft.Windows.Mobile.Provisioning.Datastore"/>
<EventProviderId Value="EventProvider_Microsoft.Windows.Mobile.Provisioning.PhoneProvisioner"/>
<EventProviderId Value="EventProvider_Microsoft.Windows.Mobile.Provisioning.PPOEM"/>
<EventProviderId Value="EventProvider_Microsoft.Windows.Provisioning.CSP"/>
<EventProviderId Value="EventProvider_Microsoft.Windows.Provisioning.Engine"/>
<EventProviderId Value="EventProvider_Microsoft.Windows.Provisioning.Migration"/>
<EventProviderId Value="EventProvider_Microsoft.Windows.Provisioning.Platform"/>
<EventProviderId Value="EventProvider_Microsoft.Windows.Provisioning.Operations"/>
<EventProviderId Value="EventProvider_Microsoft.Windows.Provisioning.Plugin.Engine"/>
<EventProviderId Value="EventProvider_Microsoft.Windows.Provisioning.Plugin.RemovableMedia"/>
<EventProviderId Value="EventProvider_Microsoft.Windows.Provisioning.ProvTool"/>
<EventProviderId Value="EventProvider_Microsoft.Windows.Provisioning.Operations"/>
<EventProviderId Value="EventProvider_Microsoft.Windows.Provisioning.CommandCsp"/>
<EventProviderId Value="EventProvider_Microsoft.Windows.Provisioning.ProvLaunch"/>
<EventProviderId Value="EventProvider_Microsoft.Windows.EMPS.Enrollment"/>
<EventProviderId Value="EventProvider_Microsoft.Windows.EnterpriseManagement.Enrollment"/>
<EventProviderId Value="Microsoft.Windows.HyperV.Vid"/>
<EventProviderId Value="Microsoft-Windows-HyperV-Vid"/>
<EventProviderId Value="virtdisk"/>
<EventProviderId Value="virtdisk_wpp"/>
<EventProviderId Value="vhdmp"/>
<EventProviderId Value="vhdmp_wpp"/>
<EventProviderId Value="storvsp"/>
<EventProviderId Value="HyperV_SyntheticStorage"/>
<EventProviderId Value="HyperV_EmulatedStorage"/>
<EventProviderId Value="EventProvider_Telemetry_StorVSP"/>
<EventProviderId Value="EventProvider_Trace_Vhdmp"/>
<EventProviderId Value="EventProvider_HvSocketTraceProvider" />
</EventProviders>
</EventCollectorId>
</Collectors>
</Profile>
</Profiles>
</WindowsPerformanceRecorder>

View File

@ -43,16 +43,16 @@
} }
}, },
{ {
"Name": "openSUSE-Leap-15.6", "Name": "openSUSE-Leap-16.0",
"FriendlyName": "openSUSE Leap 15.6", "FriendlyName": "openSUSE Leap 16.0",
"Default": false, "Default": false,
"Amd64Url": { "Amd64Url": {
"Url": "https://github.com/openSUSE/WSL-instarball/releases/download/v20250320.0/openSUSE-Leap-15.6-15.6.x86_64-15.2-Build15.2.wsl", "Url": "https://github.com/openSUSE/WSL-instarball/releases/download/v20251001.0/openSUSE-Leap-16.0-16.0.x86_64-22.57-Build22.57.wsl",
"Sha256": "0x63ea1828168026c86522743d551b2c88f0f4f94d813d2adc5881164d176b0ea1" "Sha256": "0x0d1faa095153beee0a9b5089b0f9aa3d2aec95e2cdcffdeeff84dd54c48b8393"
}, },
"Arm64Url": { "Arm64Url": {
"Url": "https://github.com/openSUSE/WSL-instarball/releases/download/v20250320.0/openSUSE-Leap-15.6-15.6.aarch64-15.2-Build15.2.wsl", "Url": "https://github.com/openSUSE/WSL-instarball/releases/download/v20251001.0/openSUSE-Leap-16.0-16.0.aarch64-22.57-Build22.57.wsl",
"Sha256": "0x0a3c646f69bb83889c4264e41030076104a2f3d71ae6a1e14a1e0653dfd2e3d4" "Sha256": "0x91bcdc7e9f42d7a60a4464ad867d91243aaaecab7b3a057039f77a989daac51e"
} }
} }
], ],
@ -166,8 +166,8 @@
"FriendlyName": "Arch Linux", "FriendlyName": "Arch Linux",
"Default": true, "Default": true,
"Amd64Url": { "Amd64Url": {
"Url": "https://geo.mirror.pkgbuild.com/wsl/2025.09.01.145298/archlinux-2025.09.01.145298.wsl", "Url": "https://geo.mirror.pkgbuild.com/wsl/2025.10.01.148042/archlinux-2025.10.01.148042.wsl",
"Sha256": "9b011093c7ad5d0dccd0be785c9d968c30b4fce3957f3f1868f2c1c4415ae841" "Sha256": "98a5792935c46476f471854bc93344b2b1d63f7947905ce4dd75d20a546db7ea"
} }
} }
], ],

View File

@ -33,7 +33,8 @@ DISCOURAGED_SYSTEM_UNITS = ['systemd-resolved.service',
'systemd-tmpfiles-setup-dev.service', 'systemd-tmpfiles-setup-dev.service',
'tmp.mount', 'tmp.mount',
'NetworkManager.service', 'NetworkManager.service',
'networking.service'] 'networking.service',
'hypervkvpd.service']
WSL1_UNSUPPORTED_XATTRS = ['security.selinux', 'security.ima', 'security.evm'] WSL1_UNSUPPORTED_XATTRS = ['security.selinux', 'security.ima', 'security.evm']

View File

@ -1108,7 +1108,7 @@ Error code: {}</value>
<data name="MessageSparseVhdDisabled" xml:space="preserve"> <data name="MessageSparseVhdDisabled" xml:space="preserve">
<value>Sparse VHD support is currently disabled due to potential data corruption. <value>Sparse VHD support is currently disabled due to potential data corruption.
To force a distribution to use a sparse vhd, please run: To force a distribution to use a sparse vhd, please run:
wsl.exe --manage &lt;DistributionName&gt; --set-sparse --allow-unsafe</value> wsl.exe --manage &lt;DistributionName&gt; --set-sparse true --allow-unsafe</value>
<comment>{Locked="--manage "}{Locked="--set-sparse "}{Locked="--allow-unsafe"}Command line arguments, file names and string inserts should not be translated</comment> <comment>{Locked="--manage "}{Locked="--set-sparse "}{Locked="--allow-unsafe"}Command line arguments, file names and string inserts should not be translated</comment>
</data> </data>
<data name="MessageDrvfsMountFailed" xml:space="preserve"> <data name="MessageDrvfsMountFailed" xml:space="preserve">

View File

@ -430,6 +430,14 @@
Execute="deferred" Execute="deferred"
/> />
<CustomAction Id="FinalizeInstall"
Impersonate="no"
BinaryRef="wslinstall.dll"
DllEntry="WslFinalizeInstallation"
Return="check"
Execute="deferred"
/>
<CustomAction Id="DeprovisionMsix" <CustomAction Id="DeprovisionMsix"
Impersonate="no" Impersonate="no"
BinaryRef="wslinstall.dll" BinaryRef="wslinstall.dll"
@ -566,6 +574,8 @@
<Custom Action="CalculateWslSettingsProtocolIds" Before="WriteRegistryValues" Condition='(not REMOVE~="ALL")' /> <Custom Action="CalculateWslSettingsProtocolIds" Before="WriteRegistryValues" Condition='(not REMOVE~="ALL")' />
<?endif?> <?endif?>
<Custom Action="FinalizeInstall" After="PublishFeatures"/>
</InstallExecuteSequence> </InstallExecuteSequence>
<!-- Don't show a 'Modify' button in settings since there is nothing to modify --> <!-- Don't show a 'Modify' button in settings since there is nothing to modify -->

View File

@ -8,8 +8,8 @@
<package id="Microsoft.DXCore.Linux.arm64fre" version="10.0.26100.1-240331-1435.ge-release" targetFramework="native" /> <package id="Microsoft.DXCore.Linux.arm64fre" version="10.0.26100.1-240331-1435.ge-release" targetFramework="native" />
<package id="Microsoft.Extensions.Hosting" version="9.0.8" /> <package id="Microsoft.Extensions.Hosting" version="9.0.8" />
<package id="Microsoft.Identity.MSAL.WSL.Proxy" version="0.1.1" /> <package id="Microsoft.Identity.MSAL.WSL.Proxy" version="0.1.1" />
<package id="Microsoft.NETCore.App.Runtime.win-arm64" version="9.0.8" /> <package id="Microsoft.NETCore.App.Runtime.win-arm64" version="9.0.10" />
<package id="Microsoft.NETCore.App.Runtime.win-x64" version="9.0.8" /> <package id="Microsoft.NETCore.App.Runtime.win-x64" version="9.0.10" />
<package id="Microsoft.RemoteDesktop.Client.MSRDC.SessionHost" version="1.2.6353" /> <package id="Microsoft.RemoteDesktop.Client.MSRDC.SessionHost" version="1.2.6353" />
<package id="Microsoft.Taef" version="10.97.250317001" targetFramework="native" /> <package id="Microsoft.Taef" version="10.97.250317001" targetFramework="native" />
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.250325.1" targetFramework="native" /> <package id="Microsoft.Windows.ImplementationLibrary" version="1.0.250325.1" targetFramework="native" />
@ -18,13 +18,13 @@
<package id="Microsoft.WSL.bsdtar" version="0.0.2-2" /> <package id="Microsoft.WSL.bsdtar" version="0.0.2-2" />
<package id="Microsoft.WSL.Dependencies.amd64fre" version="10.0.27820.1000-250318-1700.rs-base2-hyp" targetFramework="native" /> <package id="Microsoft.WSL.Dependencies.amd64fre" version="10.0.27820.1000-250318-1700.rs-base2-hyp" targetFramework="native" />
<package id="Microsoft.WSL.Dependencies.arm64fre" version="10.0.27820.1000-250318-1700.rs-base2-hyp" targetFramework="native" /> <package id="Microsoft.WSL.Dependencies.arm64fre" version="10.0.27820.1000-250318-1700.rs-base2-hyp" targetFramework="native" />
<package id="Microsoft.WSL.DeviceHost" version="1.0.0-20241009.4" /> <package id="Microsoft.WSL.DeviceHost" version="1.0.0-20251015.1" />
<package id="Microsoft.WSL.Kernel" version="6.6.87.2-1" targetFramework="native" /> <package id="Microsoft.WSL.Kernel" version="6.6.87.2-1" targetFramework="native" />
<package id="Microsoft.WSL.LinuxSdk" version="1.20.0" targetFramework="native" /> <package id="Microsoft.WSL.LinuxSdk" version="1.20.0" targetFramework="native" />
<package id="Microsoft.WSL.LxUtil.amd64fre" version="10.0.26100.1-240331-1435.ge-release" /> <package id="Microsoft.WSL.LxUtil.amd64fre" version="10.0.26100.1-240331-1435.ge-release" />
<package id="Microsoft.WSL.LxUtil.arm64fre" version="10.0.26100.1-240331-1435.ge-release" /> <package id="Microsoft.WSL.LxUtil.arm64fre" version="10.0.26100.1-240331-1435.ge-release" />
<package id="Microsoft.WSL.TestDistro" version="2.5.7-47" /> <package id="Microsoft.WSL.TestDistro" version="2.5.7-47" />
<package id="Microsoft.WSLg" version="1.0.69" /> <package id="Microsoft.WSLg" version="1.0.71" />
<package id="Microsoft.Xaml.Behaviors.WinUI.Managed" version="3.0.0" /> <package id="Microsoft.Xaml.Behaviors.WinUI.Managed" version="3.0.0" />
<package id="StrawberryPerl" version="5.28.0.1" /> <package id="StrawberryPerl" version="5.28.0.1" />
<package id="vswhere" version="3.1.7" /> <package id="vswhere" version="3.1.7" />

View File

@ -28,6 +28,7 @@ WslDistributionConfig::WslDistributionConfig(const char* configFilePath)
ConfigKey("automount.options", DrvFsOptions), ConfigKey("automount.options", DrvFsOptions),
ConfigKey(c_ConfigMountFsTabOption, MountFsTab), ConfigKey(c_ConfigMountFsTabOption, MountFsTab),
ConfigKey(c_ConfigLinkOsLibsOption, LinkOsLibs), ConfigKey(c_ConfigLinkOsLibsOption, LinkOsLibs),
ConfigKey("automount.cgroups", {{"v1", CGroupVersion::v1}, {"v2", CGroupVersion::v2}}, CGroup, nullptr),
ConfigKey("filesystem.umask", Umask), ConfigKey("filesystem.umask", Umask),

View File

@ -48,6 +48,12 @@ struct WslDistributionConfig
WslDistributionConfig(WslDistributionConfig&&) = default; WslDistributionConfig(WslDistributionConfig&&) = default;
WslDistributionConfig& operator=(WslDistributionConfig&&) = default; WslDistributionConfig& operator=(WslDistributionConfig&&) = default;
enum class CGroupVersion
{
v1 = 0,
v2 = 1
};
bool AutoMount = true; bool AutoMount = true;
bool AutoUpdateTimezone = true; bool AutoUpdateTimezone = true;
std::optional<std::string> BootCommand; std::optional<std::string> BootCommand;
@ -71,6 +77,7 @@ struct WslDistributionConfig
bool AppendGpuLibPath = true; bool AppendGpuLibPath = true;
bool GpuEnabled = true; bool GpuEnabled = true;
bool LinkOsLibs = true; bool LinkOsLibs = true;
CGroupVersion CGroup = CGroupVersion::v2;
// //
// Values not set by /etc/wsl.conf. // Values not set by /etc/wsl.conf.

View File

@ -54,9 +54,6 @@ Abstract:
#include <cstdarg> #include <cstdarg>
#include "lxinitshared.h" #include "lxinitshared.h"
#include "defs.h" #include "defs.h"
#include "retryshared.h"
#include "socketshared.h"
#include "stringshared.h"
#define ETC_FOLDER "/etc/" #define ETC_FOLDER "/etc/"
#define NAME_ENV "NAME" #define NAME_ENV "NAME"
@ -151,6 +148,11 @@ auto LogImpl(int fd, const std::format_string<Args...>& format, Args&&... args)
#define FATAL_ERROR(str, ...) FATAL_ERROR_EX(1, str, ##__VA_ARGS__) #define FATAL_ERROR(str, ...) FATAL_ERROR_EX(1, str, ##__VA_ARGS__)
// Some of these files need the LOG_* macros.
#include "retryshared.h"
#include "socketshared.h"
#include "stringshared.h"
int InitializeLogging(bool SetStderr, wil::LogFunction* ExceptionCallback = nullptr) noexcept; int InitializeLogging(bool SetStderr, wil::LogFunction* ExceptionCallback = nullptr) noexcept;
void LogException(const char* Message, const char* Description) noexcept; void LogException(const char* Message, const char* Description) noexcept;

View File

@ -73,6 +73,8 @@ Abstract:
#define MOUNTS_DEVICE_FIELD 0 #define MOUNTS_DEVICE_FIELD 0
#define MOUNTS_FSTYPE_FIELD 2 #define MOUNTS_FSTYPE_FIELD 2
using wsl::linux::WslDistributionConfig;
static void ConfigApplyWindowsLibPath(const wsl::linux::WslDistributionConfig& Config); static void ConfigApplyWindowsLibPath(const wsl::linux::WslDistributionConfig& Config);
static bool CreateLoginSession(const wsl::linux::WslDistributionConfig& Config, const char* Username, uid_t Uid); static bool CreateLoginSession(const wsl::linux::WslDistributionConfig& Config, const char* Username, uid_t Uid);
@ -567,7 +569,7 @@ Return Value:
// Initialize cgroups based on what the kernel supports. // Initialize cgroups based on what the kernel supports.
// //
ConfigInitializeCgroups(); ConfigInitializeCgroups(Config);
// //
// Attempt to register the NT interop binfmt extension. // Attempt to register the NT interop binfmt extension.
@ -1783,7 +1785,7 @@ Return Value:
{LX_WSL2_GUI_APP_SUPPORT_ENV, "1"}}; {LX_WSL2_GUI_APP_SUPPORT_ENV, "1"}};
} }
void ConfigInitializeCgroups(void) void ConfigInitializeCgroups(wsl::linux::WslDistributionConfig& Config)
/*++ /*++
@ -1795,7 +1797,7 @@ Routine Description:
Arguments: Arguments:
None. Config - Supplies the distribution configuration.
Return Value: Return Value:
@ -1805,50 +1807,82 @@ Return Value:
try try
{ {
std::vector<std::string> DisabledControllers;
//
// For WSL2 mount cgroup v2.
//
// N.B. Cgroup v2 is not implemented for WSL1.
//
if (UtilIsUtilityVm()) if (UtilIsUtilityVm())
{ {
const auto Target = CGROUP_MOUNTPOINT; if (Config.CGroup == WslDistributionConfig::CGroupVersion::v1)
{
auto commandLine = UtilReadFileContent("/proc/cmdline");
auto position = commandLine.find(CGROUPS_NO_V1);
if (position != std::string::npos)
{
auto list = commandLine.substr(position + sizeof(CGROUPS_NO_V1) - 1);
auto end = list.find_first_of(" \n");
if (end != std::string::npos)
{
list = list.substr(0, end);
}
if (list == "all")
{
LOG_WARNING("Distribution has cgroupv1 enabled, but kernel command line has {}all. Falling back to cgroupv2", CGROUPS_NO_V1);
Config.CGroup = WslDistributionConfig::CGroupVersion::v2;
}
else
{
DisabledControllers = wsl::shared::string::Split(list, ',');
}
}
}
if (Config.CGroup == WslDistributionConfig::CGroupVersion::v1)
{
THROW_LAST_ERROR_IF(mount("tmpfs", CGROUP_MOUNTPOINT, "tmpfs", (MS_NOSUID | MS_NODEV | MS_NOEXEC), "mode=755") < 0);
}
const auto Target = Config.CGroup == WslDistributionConfig::CGroupVersion::v1 ? CGROUP_MOUNTPOINT "/unified" : CGROUP_MOUNTPOINT;
THROW_LAST_ERROR_IF( THROW_LAST_ERROR_IF(
UtilMount(CGROUP2_DEVICE, Target, CGROUP2_DEVICE, (MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_RELATIME), "nsdelegate") < 0); UtilMount(CGROUP2_DEVICE, Target, CGROUP2_DEVICE, (MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_RELATIME), "nsdelegate") < 0);
if (Config.CGroup == WslDistributionConfig::CGroupVersion::v2)
{
return;
}
} }
else else
{ {
//
// Mount cgroup v1 when running in WSL1 mode.
//
// Open the /proc/cgroups file and parse each line, ignoring malformed
// lines and disabled controllers.
//
THROW_LAST_ERROR_IF(mount("tmpfs", CGROUP_MOUNTPOINT, "tmpfs", (MS_NOSUID | MS_NODEV | MS_NOEXEC), "mode=755") < 0); THROW_LAST_ERROR_IF(mount("tmpfs", CGROUP_MOUNTPOINT, "tmpfs", (MS_NOSUID | MS_NODEV | MS_NOEXEC), "mode=755") < 0);
}
wil::unique_file Cgroups{fopen(CGROUPS_FILE, "r")}; //
THROW_LAST_ERROR_IF(!Cgroups); // Mount cgroup v1 when running in WSL1 mode or when a WSL2 distro has automount.cgroups=v1 specified.
//
// Open the /proc/cgroups file and parse each line, ignoring malformed
// lines and disabled controllers.
//
wil::unique_file Cgroups{fopen(CGROUPS_FILE, "r")};
THROW_LAST_ERROR_IF(!Cgroups);
ssize_t BytesRead;
char* Line = nullptr;
auto LineCleanup = wil::scope_exit([&]() { free(Line); });
size_t LineLength = 0;
while ((BytesRead = getline(&Line, &LineLength, Cgroups.get())) != -1)
{
char* Subsystem = nullptr;
bool Enabled = false;
if ((UtilParseCgroupsLine(Line, &Subsystem, &Enabled) < 0) || (Enabled == false) ||
std::find(DisabledControllers.begin(), DisabledControllers.end(), Subsystem) != DisabledControllers.end())
ssize_t BytesRead;
char* Line = nullptr;
auto LineCleanup = wil::scope_exit([&]() { free(Line); });
size_t LineLength = 0;
while ((BytesRead = getline(&Line, &LineLength, Cgroups.get())) != -1)
{ {
char* Subsystem = nullptr; continue;
bool Enabled = false;
if ((UtilParseCgroupsLine(Line, &Subsystem, &Enabled) < 0) || (Enabled == false))
{
continue;
}
auto Target = std::format("{}/{}", CGROUP_MOUNTPOINT, Subsystem);
THROW_LAST_ERROR_IF(
UtilMount(CGROUP_DEVICE, Target.c_str(), CGROUP_DEVICE, (MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_RELATIME), Subsystem) < 0);
} }
auto Target = std::format("{}/{}", CGROUP_MOUNTPOINT, Subsystem);
THROW_LAST_ERROR_IF(
UtilMount(CGROUP_DEVICE, Target.c_str(), CGROUP_DEVICE, (MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_RELATIME), Subsystem) < 0);
} }
} }
CATCH_LOG() CATCH_LOG()

View File

@ -406,7 +406,7 @@ void ConfigHandleInteropMessage(
const MESSAGE_HEADER* Header, const MESSAGE_HEADER* Header,
const wsl::linux::WslDistributionConfig& Config); const wsl::linux::WslDistributionConfig& Config);
void ConfigInitializeCgroups(void); void ConfigInitializeCgroups(wsl::linux::WslDistributionConfig& Config);
int ConfigInitializeInstance(wsl::shared::SocketChannel& Channel, gsl::span<gsl::byte> Buffer, wsl::linux::WslDistributionConfig& Config); int ConfigInitializeInstance(wsl::shared::SocketChannel& Channel, gsl::span<gsl::byte> Buffer, wsl::linux::WslDistributionConfig& Config);

View File

@ -129,6 +129,8 @@ void InitEntryUtilityVm(wsl::linux::WslDistributionConfig& Config);
void InitTerminateInstance(gsl::span<gsl::byte> Buffer, wsl::shared::SocketChannel& Channel, wsl::linux::WslDistributionConfig& Config); void InitTerminateInstance(gsl::span<gsl::byte> Buffer, wsl::shared::SocketChannel& Channel, wsl::linux::WslDistributionConfig& Config);
void InitTerminateInstanceInternal(const wsl::linux::WslDistributionConfig& Config);
void InstallSystemdUnit(const char* Path, const std::string& Name, const char* Content); void InstallSystemdUnit(const char* Path, const std::string& Name, const char* Content);
int GenerateSystemdUnits(int Argc, char** Argv); int GenerateSystemdUnits(int Argc, char** Argv);
@ -2507,18 +2509,7 @@ Return Value:
} }
} }
// InitTerminateInstanceInternal(Config);
// If the distro init process was booted, use the shutdown command to terminate the instance.
//
if (Config.BootInit && !Config.BootStartWriteSocket)
{
UtilExecCommandLine("systemctl reboot", nullptr);
}
reboot(RB_POWER_OFF);
FATAL_ERROR("reboot(RB_POWER_OFF) failed {}", errno);
return; return;
} }
@ -2661,10 +2652,56 @@ try
} }
// //
// Respond to the instance termination request. // Attempt to stop the plan9 server, if it is not able to be stopped because of an
// in-use file, reply to the service that the instance could not be terminated.
// //
Channel.SendResultMessage<bool>(StopPlan9Server(Message->Force, Config)); if (!StopPlan9Server(Message->Force, Config))
{
Channel.SendResultMessage<bool>(false);
return;
}
InitTerminateInstanceInternal(Config);
}
CATCH_LOG();
void InitTerminateInstanceInternal(const wsl::linux::WslDistributionConfig& Config)
/*++
Routine Description:
This routine attempts to cleanly terminate the instance.
Arguments:
Config - Supplies the distribution config.
Return Value:
None.
--*/
try
{
//
// If systemd is enabled, attempt to poweroff the instance via systemctl.
//
if (Config.BootInit && !Config.BootStartWriteSocket)
{
THROW_LAST_ERROR_IF(UtilSetSignalHandlers(g_SavedSignalActions, false) < 0);
if (UtilExecCommandLine("systemctl poweroff", nullptr) == 0)
{
std::this_thread::sleep_for(std::chrono::milliseconds(Config.BootInitTimeout));
LOG_ERROR("systemctl poweroff did not terminate the instance in {} ms, calling reboot(RB_POWER_OFF)", Config.BootInitTimeout);
}
}
reboot(RB_POWER_OFF);
FATAL_ERROR("reboot(RB_POWER_OFF) failed {}", errno);
} }
CATCH_LOG(); CATCH_LOG();

View File

@ -857,10 +857,10 @@ Return Value:
if (WI_IsFlagSet(Flags, LxMiniInitMessageFlagVerbose)) if (WI_IsFlagSet(Flags, LxMiniInitMessageFlagVerbose))
{ {
compressionArguments += "v"; compressionArguments += "vv";
} }
const char* arguments[] = { std::vector<const char*> arguments{
BSDTAR_PATH, BSDTAR_PATH,
"-C", "-C",
Source, Source,
@ -872,7 +872,13 @@ Return Value:
"-", "-",
".", ".",
nullptr}; nullptr};
execv(BSDTAR_PATH, const_cast<char**>(arguments));
if (WI_IsFlagSet(Flags, LxMiniInitMessageFlagVerbose))
{
arguments.emplace(arguments.begin() + 3, "--totals");
}
execv(BSDTAR_PATH, const_cast<char**>(arguments.data()));
LOG_ERROR("execl failed, {}", errno); LOG_ERROR("execl failed, {}", errno);
}); });
@ -1158,7 +1164,7 @@ Return Value:
"-C", "-C",
Destination, Destination,
"-x", "-x",
WI_IsFlagSet(Flags, LxMiniInitMessageFlagVerbose) ? "-vp" : "-p", WI_IsFlagSet(Flags, LxMiniInitMessageFlagVerbose) ? "-vvp" : "-p",
"--xattrs", "--xattrs",
"--numeric-owner", "--numeric-owner",
"-f", "-f",
@ -3877,6 +3883,63 @@ int WslEntryPoint(int Argc, char* Argv[]);
extern int WSLAEntryPoint(int Argc, char* Argv[]); extern int WSLAEntryPoint(int Argc, char* Argv[]);
void EnableDebugMode(const std::string& Mode)
{
if (Mode == "hvsocket")
{
// Mount the debugfs.
THROW_LAST_ERROR_IF(UtilMount("none", "/sys/kernel/debug", "debugfs", 0, nullptr) < 0);
// Enable hvsocket events.
std::vector<const char*> files{
"/sys/kernel/debug/tracing/events/hyperv/vmbus_on_msg_dpc/enable",
"/sys/kernel/debug/tracing/events/hyperv/vmbus_on_message/enable",
"/sys/kernel/debug/tracing/events/hyperv/vmbus_onoffer/enable",
"/sys/kernel/debug/tracing/events/hyperv/vmbus_onoffer_rescind/enable",
"/sys/kernel/debug/tracing/events/hyperv/vmbus_onopen_result/enable",
"/sys/kernel/debug/tracing/events/hyperv/vmbus_ongpadl_created/enable",
"/sys/kernel/debug/tracing/events/hyperv/vmbus_ongpadl_torndown/enable",
"/sys/kernel/debug/tracing/events/hyperv/vmbus_open/enable",
"/sys/kernel/debug/tracing/events/hyperv/vmbus_close_internal/enable",
"/sys/kernel/debug/tracing/events/hyperv/vmbus_establish_gpadl_header/enable",
"/sys/kernel/debug/tracing/events/hyperv/vmbus_establish_gpadl_body/enable",
"/sys/kernel/debug/tracing/events/hyperv/vmbus_teardown_gpadl/enable",
"/sys/kernel/debug/tracing/events/hyperv/vmbus_release_relid/enable",
"/sys/kernel/debug/tracing/events/hyperv/vmbus_send_tl_connect_request/enable"};
for (auto* e : files)
{
WriteToFile(e, "1");
}
// Relay logs to the host.
std::thread relayThread{[]() {
constexpr auto path = "/sys/kernel/debug/tracing/trace_pipe";
std::ifstream file(path);
if (!file)
{
LOG_ERROR("Failed to open {}, {}", path, errno);
return;
}
std::string line;
while (std::getline(file, line))
{
LOG_INFO("{}", line);
}
LOG_ERROR("{}: closed", path);
}};
relayThread.detach();
}
else
{
LOG_ERROR("Unknown debugging mode: '{}'", Mode);
}
}
int main(int Argc, char* Argv[]) int main(int Argc, char* Argv[])
{ {
std::vector<gsl::byte> Buffer; std::vector<gsl::byte> Buffer;
@ -4009,6 +4072,37 @@ int main(int Argc, char* Argv[])
} }
} }
//
// Create the etc directory and mount procfs and sysfs.
//
if (UtilMkdir(ETC_PATH, 0755) < 0)
{
return -1;
}
if (UtilMount(nullptr, PROCFS_PATH, "proc", 0, nullptr) < 0)
{
return -1;
}
if (UtilMount(nullptr, SYSFS_PATH, "sysfs", 0, nullptr) < 0)
{
return -1;
}
//
// Enable debug mode, if specified.
//
if (const auto* debugMode = getenv(WSL_DEBUG_ENV))
{
LOG_ERROR("Running in debug mode: '{}'", debugMode);
EnableDebugMode(debugMode);
unsetenv(WSL_DEBUG_ENV);
}
// //
// Establish the message channel with the service via hvsocket. // Establish the message channel with the service via hvsocket.
// //
@ -4036,25 +4130,6 @@ int main(int Argc, char* Argv[])
goto ErrorExit; goto ErrorExit;
} }
//
// Create the etc directory and mount procfs and sysfs.
//
if (UtilMkdir(ETC_PATH, 0755) < 0)
{
return -1;
}
if (UtilMount(nullptr, PROCFS_PATH, "proc", 0, nullptr) < 0)
{
return -1;
}
if (UtilMount(nullptr, SYSFS_PATH, "sysfs", 0, nullptr) < 0)
{
return -1;
}
if (getenv(WSL_ENABLE_CRASH_DUMP_ENV)) if (getenv(WSL_ENABLE_CRASH_DUMP_ENV))
{ {
Config.EnableCrashDumpCollection = true; Config.EnableCrashDumpCollection = true;

View File

@ -537,7 +537,7 @@ Return Value:
return Socket; return Socket;
} }
wil::unique_fd UtilConnectVsock(unsigned int Port, bool CloseOnExec, std::optional<int> SocketBuffer) noexcept wil::unique_fd UtilConnectVsock(unsigned int Port, bool CloseOnExec, std::optional<int> SocketBuffer, const std::source_location& Source) noexcept
/*++ /*++
@ -553,6 +553,8 @@ Arguments:
SocketBuffer - Optionally supplies the size to use for the socket send and receive buffers. SocketBuffer - Optionally supplies the size to use for the socket send and receive buffers.
Source - Supplies the caller location.
Return Value: Return Value:
A file descriptor representing the connected socket, -1 on failure. A file descriptor representing the connected socket, -1 on failure.
@ -565,7 +567,7 @@ Return Value:
wil::unique_fd SocketFd{socket(AF_VSOCK, Type, 0)}; wil::unique_fd SocketFd{socket(AF_VSOCK, Type, 0)};
if (!SocketFd) if (!SocketFd)
{ {
LOG_ERROR("socket failed {}", errno); LOG_ERROR("socket failed {} (from: {})", errno, Source);
return {}; return {};
} }
@ -577,7 +579,7 @@ Return Value:
Timeout.tv_sec = LX_INIT_HVSOCKET_TIMEOUT_SECONDS; Timeout.tv_sec = LX_INIT_HVSOCKET_TIMEOUT_SECONDS;
if (setsockopt(SocketFd.get(), AF_VSOCK, SO_VM_SOCKETS_CONNECT_TIMEOUT, &Timeout, sizeof(Timeout)) < 0) if (setsockopt(SocketFd.get(), AF_VSOCK, SO_VM_SOCKETS_CONNECT_TIMEOUT, &Timeout, sizeof(Timeout)) < 0)
{ {
LOG_ERROR("setsockopt SO_VM_SOCKETS_CONNECT_TIMEOUT failed {}", errno); LOG_ERROR("setsockopt SO_VM_SOCKETS_CONNECT_TIMEOUT failed {}, (from: {})", errno, Source);
return {}; return {};
} }
@ -586,13 +588,13 @@ Return Value:
int BufferSize = *SocketBuffer; int BufferSize = *SocketBuffer;
if (setsockopt(SocketFd.get(), SOL_SOCKET, SO_SNDBUF, &BufferSize, sizeof(BufferSize)) < 0) if (setsockopt(SocketFd.get(), SOL_SOCKET, SO_SNDBUF, &BufferSize, sizeof(BufferSize)) < 0)
{ {
LOG_ERROR("setsockopt(SO_SNDBUF, {}) failed {}", BufferSize, errno); LOG_ERROR("setsockopt(SO_SNDBUF, {}) failed {}, (from: {})", BufferSize, errno, Source);
return {}; return {};
} }
if (setsockopt(SocketFd.get(), SOL_SOCKET, SO_RCVBUF, &BufferSize, sizeof(BufferSize)) < 0) if (setsockopt(SocketFd.get(), SOL_SOCKET, SO_RCVBUF, &BufferSize, sizeof(BufferSize)) < 0)
{ {
LOG_ERROR("setsockopt(SO_RCVBUF, {}) failed {}", BufferSize, errno); LOG_ERROR("setsockopt(SO_RCVBUF, {}) failed {}, (from: {})", BufferSize, errno, Source);
return {}; return {};
} }
} }
@ -603,7 +605,7 @@ Return Value:
SocketAddress.svm_port = Port; SocketAddress.svm_port = Port;
if (connect(SocketFd.get(), (const struct sockaddr*)&SocketAddress, sizeof(SocketAddress)) < 0) if (connect(SocketFd.get(), (const struct sockaddr*)&SocketAddress, sizeof(SocketAddress)) < 0)
{ {
LOG_ERROR("connect port {} failed {}", Port, errno); LOG_ERROR("connect port {} failed {} (from: {})", Port, errno, Source);
return {}; return {};
} }

View File

@ -28,6 +28,7 @@ Abstract:
#include <future> #include <future>
#include <filesystem> #include <filesystem>
#include <vector> #include <vector>
#include <source_location>
#include "lxinitshared.h" #include "lxinitshared.h"
#include "lxdef.h" #include "lxdef.h"
#include "common.h" #include "common.h"
@ -128,7 +129,8 @@ wil::unique_fd UtilConnectToInteropServer(std::optional<pid_t> Pid = {});
wil::unique_fd UtilConnectUnix(const char* Path); wil::unique_fd UtilConnectUnix(const char* Path);
wil::unique_fd UtilConnectVsock(unsigned int Port, bool CloseOnExec, std::optional<int> SocketBuffer = {}) noexcept; wil::unique_fd UtilConnectVsock(
unsigned int Port, bool CloseOnExec, std::optional<int> SocketBuffer = {}, const std::source_location& Source = std::source_location::current()) noexcept;
// Needs to be declared before UtilCreateChildProcess(). // Needs to be declared before UtilCreateChildProcess().
void UtilSetThreadName(const char* Name); void UtilSetThreadName(const char* Name);

View File

@ -46,18 +46,18 @@ std::wstring ToJsonW(const T& Value)
return wsl::shared::string::MultiByteToWide(ToJson(Value)); return wsl::shared::string::MultiByteToWide(ToJson(Value));
} }
template <typename T> template <typename T, typename TJson = nlohmann::json>
T FromJson(const char* Value) T FromJson(const char* Value)
{ {
try try
{ {
auto json = nlohmann::json::parse(Value); auto json = TJson::parse(Value);
T object{}; T object{};
from_json(json, object); from_json(json, object);
return object; return object;
} }
catch (const nlohmann::json::exception& e) catch (const TJson::exception& e)
{ {
#ifdef WIN32 #ifdef WIN32
@ -72,10 +72,10 @@ T FromJson(const char* Value)
} }
} }
template <typename T> template <typename T, typename TJson = nlohmann::json>
T FromJson(const wchar_t* Value) T FromJson(const wchar_t* Value)
{ {
return FromJson<T>(wsl::shared::string::WideToMultiByte(Value).c_str()); return FromJson<T, TJson>(wsl::shared::string::WideToMultiByte(Value).c_str());
} }
template <typename T> template <typename T>

View File

@ -111,12 +111,13 @@ public:
#ifdef WIN32 #ifdef WIN32
auto sentBytes = wsl::windows::common::socket::Send(m_socket.get(), span, m_exitEvent);
WSL_LOG( WSL_LOG(
"SentMessage", "SentMessage",
TraceLoggingValue(m_name.c_str(), "Name"), TraceLoggingValue(m_name.c_str(), "Name"),
TraceLoggingValue(reinterpret_cast<const TMessage*>(span.data())->PrettyPrint().c_str(), "Content")); TraceLoggingValue(reinterpret_cast<const TMessage*>(span.data())->PrettyPrint().c_str(), "Content"),
TraceLoggingValue(sentBytes, "SentBytes"));
wsl::windows::common::socket::Send(m_socket.get(), span, m_exitEvent);
#else #else
@ -129,7 +130,7 @@ public:
{ {
LOG_ERROR("Failed to write message {}. Channel: {}", header->MessageType, m_name); LOG_ERROR("Failed to write message {}. Channel: {}", header->MessageType, m_name);
THROW_LAST_ERROR(); THROW_LAST_ERROR();
}; }
#endif #endif
} }

View File

@ -193,6 +193,8 @@ Abstract:
#define WSL_ENABLE_CRASH_DUMP_ENV "WSL_ENABLE_CRASH_DUMP" #define WSL_ENABLE_CRASH_DUMP_ENV "WSL_ENABLE_CRASH_DUMP"
#define WSL_DEBUG_ENV "WSL_DEBUG"
#define WSL_DISTRIBUTION_CONF "/etc/wsl-distribution.conf" #define WSL_DISTRIBUTION_CONF "/etc/wsl-distribution.conf"
// //

View File

@ -80,6 +80,27 @@ try
#endif #endif
if (BytesRead <= 0) if (BytesRead <= 0)
{ {
const auto* Header = reinterpret_cast<const MESSAGE_HEADER*>(Buffer.data());
#if defined(_MSC_VER)
LOG_HR_MSG(
E_UNEXPECTED,
"Socket closed while reading message. Size: %u, type: %i, sequence: %u",
Header->MessageSize,
Header->MessageType,
Header->SequenceNumber);
#elif defined(__GNUC__)
LOG_ERROR(
"Socket closed while reading message. Size: {}, type: {}, sequence: {}",
Header->MessageSize,
Header->MessageType,
Header->SequenceNumber);
#endif
return {}; return {};
} }

View File

@ -20,6 +20,7 @@ Abstract:
#include <fstream> #include <fstream>
#include <gsl/gsl> #include <gsl/gsl>
#include <format> #include <format>
#include <source_location>
#ifndef WIN32 #ifndef WIN32
#include <string.h> #include <string.h>
@ -861,6 +862,22 @@ struct std::formatter<wchar_t[N], char>
} }
}; };
template <>
struct std::formatter<std::source_location, char>
{
template <typename TCtx>
static constexpr auto parse(TCtx& ctx)
{
return ctx.begin();
}
template <typename TCtx>
auto format(const std::source_location& location, TCtx& ctx) const
{
return std::format_to(ctx.out(), "{}[{}:{}]", location.function_name(), location.file_name(), location.line());
}
};
template <> template <>
struct std::formatter<char*, wchar_t> struct std::formatter<char*, wchar_t>
{ {

View File

@ -112,7 +112,7 @@ DistributionList ReadFromManifest(const std::wstring& url)
content = response.Content().ReadAsStringAsync().get(); content = response.Content().ReadAsStringAsync().get();
} }
auto distros = wsl::shared::FromJson<DistributionList>(content.c_str()); auto distros = wsl::shared::FromJson<DistributionList, nlohmann::ordered_json>(content.c_str());
if (distros.Distributions.has_value()) if (distros.Distributions.has_value())
{ {

View File

@ -58,10 +58,28 @@ struct Distribution
struct DistributionList struct DistributionList
{ {
std::optional<std::vector<Distribution>> Distributions; std::optional<std::vector<Distribution>> Distributions;
std::optional<std::map<std::string, std::vector<ModernDistributionVersion>>> ModernDistributions; std::optional<nlohmann::ordered_map<std::string, std::vector<ModernDistributionVersion>>> ModernDistributions;
std::optional<std::wstring> Default; std::optional<std::wstring> Default;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(DistributionList, Distributions, ModernDistributions, Default) friend void from_json(const nlohmann::ordered_json& nlohmann_json_j, DistributionList& nlohmann_json_t)
{
const DistributionList nlohmann_json_default_obj{};
NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, Distributions, Default));
auto modernDistributions = nlohmann_json_j.find("ModernDistributions");
if (modernDistributions != nlohmann_json_j.end())
{
nlohmann_json_t.ModernDistributions.emplace();
for (const auto& e : modernDistributions->items())
{
std::vector<ModernDistributionVersion> distros;
from_json(e.value(), distros);
nlohmann_json_t.ModernDistributions->emplace_back(e.key(), std::move(distros));
}
}
}
}; };
constexpr inline auto c_distroUrlRegistryValue = L"DistributionListUrl"; constexpr inline auto c_distroUrlRegistryValue = L"DistributionListUrl";

View File

@ -19,7 +19,6 @@ Abstract:
// Defines. // Defines.
#define LAUNCH_PROCESS_DEFAULT_BUFFER_SIZE 1024 #define LAUNCH_PROCESS_DEFAULT_BUFFER_SIZE 1024
#define LAUNCH_PROCESS_DEFAULT_TIMEOUT_MS 30000
LxssMessagePort::LxssMessagePort(_In_ HANDLE MessagePort) : m_messagePort(MessagePort), m_messageEvent(wil::EventOptions::None) LxssMessagePort::LxssMessagePort(_In_ HANDLE MessagePort) : m_messagePort(MessagePort), m_messageEvent(wil::EventOptions::None)
{ {
@ -52,7 +51,7 @@ std::shared_ptr<LxssPort> LxssMessagePort::CreateSessionLeader(_In_ HANDLE Clien
LX_INIT_CREATE_SESSION Message{{LxInitMessageCreateSession, sizeof(Message)}, MarshalId}; LX_INIT_CREATE_SESSION Message{{LxInitMessageCreateSession, sizeof(Message)}, MarshalId};
Send(&Message, sizeof(Message)); Send(&Message, sizeof(Message));
auto LocalMessagePort = m_serverPort->WaitForConnection(LAUNCH_PROCESS_DEFAULT_TIMEOUT_MS); auto LocalMessagePort = m_serverPort->WaitForConnection(c_defaultMessageTimeout);
ReleaseConsole.release(); ReleaseConsole.release();
return LocalMessagePort; return LocalMessagePort;
} }
@ -156,7 +155,7 @@ void LxssMessagePort::Receive(_Out_writes_bytes_(Length) PVOID Buffer, _In_ ULON
return; return;
} }
std::vector<gsl::byte> LxssMessagePort::Receive() std::vector<gsl::byte> LxssMessagePort::Receive(DWORD Timeout)
{ {
IO_STATUS_BLOCK IoStatus; IO_STATUS_BLOCK IoStatus;
std::vector<gsl::byte> Message; std::vector<gsl::byte> Message;
@ -170,7 +169,7 @@ std::vector<gsl::byte> LxssMessagePort::Receive()
if (Status == STATUS_PENDING) if (Status == STATUS_PENDING)
{ {
WaitForMessage(&IoStatus); WaitForMessage(&IoStatus, Timeout);
Status = IoStatus.Status; Status = IoStatus.Status;
SizeReceived = static_cast<ULONG>(IoStatus.Information); SizeReceived = static_cast<ULONG>(IoStatus.Information);
} }
@ -274,7 +273,7 @@ wil::unique_handle LxssMessagePort::UnmarshalVfsFile(_In_ LXBUS_IPC_HANDLE_ID Vf
void LxssMessagePort::WaitForMessage(_In_ PIO_STATUS_BLOCK IoStatus, _In_ DWORD Timeout) const void LxssMessagePort::WaitForMessage(_In_ PIO_STATUS_BLOCK IoStatus, _In_ DWORD Timeout) const
{ {
const DWORD WaitStatus = WaitForSingleObject(m_messageEvent.get(), LAUNCH_PROCESS_DEFAULT_TIMEOUT_MS); const DWORD WaitStatus = WaitForSingleObject(m_messageEvent.get(), Timeout);
if (WaitStatus == WAIT_TIMEOUT) if (WaitStatus == WAIT_TIMEOUT)
{ {
IO_STATUS_BLOCK IoStatusCancel; IO_STATUS_BLOCK IoStatusCancel;

View File

@ -21,6 +21,8 @@ class LxssServerPort;
class LxssMessagePort : public LxssPort class LxssMessagePort : public LxssPort
{ {
public: public:
static inline DWORD c_defaultMessageTimeout = 30000;
LxssMessagePort(_In_ HANDLE MessagePort); LxssMessagePort(_In_ HANDLE MessagePort);
LxssMessagePort(_In_ LxssMessagePort&& Source); LxssMessagePort(_In_ LxssMessagePort&& Source);
LxssMessagePort(_In_ std::unique_ptr<LxssMessagePort>&& SourcePointer); LxssMessagePort(_In_ std::unique_ptr<LxssMessagePort>&& SourcePointer);
@ -46,7 +48,7 @@ public:
LXBUS_IPC_PROCESS_ID LXBUS_IPC_PROCESS_ID
MarshalProcess(_In_ HANDLE ProcessHandle, _In_ bool TerminateOnClose) const; MarshalProcess(_In_ HANDLE ProcessHandle, _In_ bool TerminateOnClose) const;
std::vector<gsl::byte> Receive(); std::vector<gsl::byte> Receive(DWORD Timeout = c_defaultMessageTimeout);
void ReleaseConsole(_In_ LXBUS_IPC_CONSOLE_ID ConsoleId) const; void ReleaseConsole(_In_ LXBUS_IPC_CONSOLE_ID ConsoleId) const;

View File

@ -37,15 +37,17 @@ void InitializeWildcardSocketAddress(_Out_ PSOCKADDR_HV Address)
} }
} // namespace } // namespace
wil::unique_socket wsl::windows::common::hvsocket::Accept(_In_ SOCKET ListenSocket, _In_ int Timeout, _In_opt_ HANDLE ExitHandle) wil::unique_socket wsl::windows::common::hvsocket::Accept(
_In_ SOCKET ListenSocket, _In_ int Timeout, _In_opt_ HANDLE ExitHandle, _In_ const std::source_location& Location)
{ {
wil::unique_socket Socket = Create(); wil::unique_socket Socket = Create();
wsl::windows::common::socket::Accept(ListenSocket, Socket.get(), Timeout, ExitHandle); wsl::windows::common::socket::Accept(ListenSocket, Socket.get(), Timeout, ExitHandle, Location);
return Socket; return Socket;
} }
wil::unique_socket wsl::windows::common::hvsocket::Connect(_In_ const GUID& VmId, _In_ unsigned long Port, _In_opt_ HANDLE ExitHandle, _In_opt_ ULONG Timeout) wil::unique_socket wsl::windows::common::hvsocket::Connect(
_In_ const GUID& VmId, _In_ unsigned long Port, _In_opt_ HANDLE ExitHandle, _In_opt_ ULONG Timeout, _In_ const std::source_location& Location)
{ {
OVERLAPPED Overlapped{}; OVERLAPPED Overlapped{};
const wil::unique_event OverlappedEvent(wil::EventOptions::ManualReset); const wil::unique_event OverlappedEvent(wil::EventOptions::ManualReset);
@ -69,7 +71,7 @@ wil::unique_socket wsl::windows::common::hvsocket::Connect(_In_ const GUID& VmId
if (Result != 0) if (Result != 0)
{ {
socket::GetResult(Socket.get(), Overlapped, INFINITE, ExitHandle); socket::GetResult(Socket.get(), Overlapped, INFINITE, ExitHandle, Location);
} }
THROW_LAST_ERROR_IF_MSG( THROW_LAST_ERROR_IF_MSG(
@ -85,7 +87,7 @@ wil::unique_socket wsl::windows::common::hvsocket::Connect(_In_ const GUID& VmId
const BOOL Success = ConnectFn(Socket.get(), reinterpret_cast<sockaddr*>(&Addr), sizeof(Addr), nullptr, 0, nullptr, &Overlapped); const BOOL Success = ConnectFn(Socket.get(), reinterpret_cast<sockaddr*>(&Addr), sizeof(Addr), nullptr, 0, nullptr, &Overlapped);
if (Success == FALSE) if (Success == FALSE)
{ {
socket::GetResult(Socket.get(), Overlapped, INFINITE, ExitHandle); socket::GetResult(Socket.get(), Overlapped, INFINITE, ExitHandle, Location);
} }
return Socket; return Socket;

View File

@ -19,10 +19,18 @@ Abstract:
namespace wsl::windows::common::hvsocket { namespace wsl::windows::common::hvsocket {
constexpr ULONG c_connectTimeoutMs = 30 * 1000; wil::unique_socket Accept(
wil::unique_socket Accept(_In_ SOCKET ListenSocket, _In_ int Timeout, _In_opt_ HANDLE ExitHandle = nullptr); _In_ SOCKET ListenSocket,
_In_ int Timeout,
_In_opt_ HANDLE ExitHandle = nullptr,
const std::source_location& Location = std::source_location::current());
wil::unique_socket Connect(_In_ const GUID& VmId, _In_ unsigned long Port, _In_opt_ HANDLE ExitHandle = nullptr, ULONG Timeout = c_connectTimeoutMs); wil::unique_socket Connect(
_In_ const GUID& VmId,
_In_ unsigned long Port,
_In_opt_ HANDLE ExitHandle = nullptr,
ULONG Timeout = 30000, // TODO: Fix
const std::source_location& Location = std::source_location::current());
wil::unique_socket Create(); wil::unique_socket Create();

View File

@ -17,7 +17,8 @@ Abstract:
#include "socket.hpp" #include "socket.hpp"
#pragma hdrstop #pragma hdrstop
void wsl::windows::common::socket::Accept(_In_ SOCKET ListenSocket, _In_ SOCKET Socket, _In_ int Timeout, _In_opt_ HANDLE ExitHandle) void wsl::windows::common::socket::Accept(
_In_ SOCKET ListenSocket, _In_ SOCKET Socket, _In_ int Timeout, _In_opt_ HANDLE ExitHandle, _In_ const std::source_location& Location)
{ {
CHAR AcceptBuffer[2 * sizeof(SOCKADDR_STORAGE)]{}; CHAR AcceptBuffer[2 * sizeof(SOCKADDR_STORAGE)]{};
DWORD BytesReturned; DWORD BytesReturned;
@ -29,17 +30,20 @@ void wsl::windows::common::socket::Accept(_In_ SOCKET ListenSocket, _In_ SOCKET
if (!Success) if (!Success)
{ {
GetResult(ListenSocket, Overlapped, Timeout, ExitHandle); GetResult(ListenSocket, Overlapped, Timeout, ExitHandle, Location);
} }
// Set the accept context to mark the socket as connected. // Set the accept context to mark the socket as connected.
THROW_LAST_ERROR_IF( THROW_LAST_ERROR_IF_MSG(
setsockopt(Socket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, reinterpret_cast<char*>(&ListenSocket), sizeof(ListenSocket)) == SOCKET_ERROR); setsockopt(Socket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, reinterpret_cast<char*>(&ListenSocket), sizeof(ListenSocket)) == SOCKET_ERROR,
"From: %hs",
std::format("{}", Location).c_str());
return; return;
} }
std::pair<DWORD, DWORD> wsl::windows::common::socket::GetResult(_In_ SOCKET Socket, _In_ OVERLAPPED& Overlapped, _In_ DWORD Timeout, _In_ HANDLE ExitHandle) std::pair<DWORD, DWORD> wsl::windows::common::socket::GetResult(
_In_ SOCKET Socket, _In_ OVERLAPPED& Overlapped, _In_ DWORD Timeout, _In_ HANDLE ExitHandle, _In_ const std::source_location& Location)
{ {
const int error = WSAGetLastError(); const int error = WSAGetLastError();
THROW_HR_IF(HRESULT_FROM_WIN32(error), error != WSA_IO_PENDING); THROW_HR_IF(HRESULT_FROM_WIN32(error), error != WSA_IO_PENDING);
@ -64,7 +68,7 @@ std::pair<DWORD, DWORD> wsl::windows::common::socket::GetResult(_In_ SOCKET Sock
return {0, 0}; return {0, 0};
} }
THROW_HR_IF(HCS_E_CONNECTION_TIMEOUT, (waitStatus != WAIT_OBJECT_0)); THROW_HR_IF_MSG(HCS_E_CONNECTION_TIMEOUT, (waitStatus != WAIT_OBJECT_0), "From: %hs", std::format("{}", Location).c_str());
cancelFunction.release(); cancelFunction.release();
const bool result = WSAGetOverlappedResult(Socket, &Overlapped, &bytesProcessed, FALSE, &flagsReturned); const bool result = WSAGetOverlappedResult(Socket, &Overlapped, &bytesProcessed, FALSE, &flagsReturned);
@ -83,16 +87,17 @@ std::pair<DWORD, DWORD> wsl::windows::common::socket::GetResult(_In_ SOCKET Sock
return {bytesProcessed, flagsReturned}; return {bytesProcessed, flagsReturned};
} }
int wsl::windows::common::socket::Receive(_In_ SOCKET Socket, _In_ gsl::span<gsl::byte> Buffer, _In_opt_ HANDLE ExitHandle, _In_ DWORD Flags, _In_ DWORD Timeout) int wsl::windows::common::socket::Receive(
_In_ SOCKET Socket, _In_ gsl::span<gsl::byte> Buffer, _In_opt_ HANDLE ExitHandle, _In_ DWORD Flags, _In_ DWORD Timeout, _In_ const std::source_location& Location)
{ {
const int BytesRead = ReceiveNoThrow(Socket, Buffer, ExitHandle, Flags, Timeout); const int BytesRead = ReceiveNoThrow(Socket, Buffer, ExitHandle, Flags, Timeout, Location);
THROW_LAST_ERROR_IF(BytesRead == SOCKET_ERROR); THROW_LAST_ERROR_IF(BytesRead == SOCKET_ERROR);
return BytesRead; return BytesRead;
} }
int wsl::windows::common::socket::ReceiveNoThrow( int wsl::windows::common::socket::ReceiveNoThrow(
_In_ SOCKET Socket, _In_ gsl::span<gsl::byte> Buffer, _In_opt_ HANDLE ExitHandle, _In_ DWORD Flags, _In_ DWORD Timeout) _In_ SOCKET Socket, _In_ gsl::span<gsl::byte> Buffer, _In_opt_ HANDLE ExitHandle, _In_ DWORD Flags, _In_ DWORD Timeout, _In_ const std::source_location& Location)
{ {
OVERLAPPED Overlapped{}; OVERLAPPED Overlapped{};
const wil::unique_event OverlappedEvent(wil::EventOptions::ManualReset); const wil::unique_event OverlappedEvent(wil::EventOptions::ManualReset);
@ -103,7 +108,7 @@ int wsl::windows::common::socket::ReceiveNoThrow(
try try
{ {
BytesReturned = SOCKET_ERROR; BytesReturned = SOCKET_ERROR;
auto [innerBytes, Flags] = GetResult(Socket, Overlapped, Timeout, ExitHandle); auto [innerBytes, Flags] = GetResult(Socket, Overlapped, Timeout, ExitHandle, Location);
BytesReturned = innerBytes; BytesReturned = innerBytes;
} }
catch (...) catch (...)
@ -116,33 +121,60 @@ int wsl::windows::common::socket::ReceiveNoThrow(
return BytesReturned; return BytesReturned;
} }
std::vector<gsl::byte> wsl::windows::common::socket::Receive(_In_ SOCKET Socket, _In_opt_ HANDLE ExitHandle, _In_ DWORD Timeout) std::vector<gsl::byte> wsl::windows::common::socket::Receive(
_In_ SOCKET Socket, _In_opt_ HANDLE ExitHandle, _In_ DWORD Timeout, _In_ const std::source_location& Location)
{ {
Receive(Socket, {}, ExitHandle, MSG_PEEK); Receive(Socket, {}, ExitHandle, MSG_PEEK, Timeout, Location);
ULONG Size = 0; ULONG Size = 0;
THROW_LAST_ERROR_IF(ioctlsocket(Socket, FIONREAD, &Size) == SOCKET_ERROR); THROW_LAST_ERROR_IF(ioctlsocket(Socket, FIONREAD, &Size) == SOCKET_ERROR);
std::vector<gsl::byte> Buffer(Size); std::vector<gsl::byte> Buffer(Size);
WI_VERIFY(Receive(Socket, gsl::make_span(Buffer), ExitHandle, Timeout) == static_cast<int>(Size)); WI_VERIFY(Receive(Socket, gsl::make_span(Buffer), ExitHandle, MSG_WAITALL, Timeout, Location) == static_cast<int>(Size));
return Buffer; return Buffer;
} }
int wsl::windows::common::socket::Send(_In_ SOCKET Socket, _In_ gsl::span<const gsl::byte> Buffer, _In_opt_ HANDLE ExitHandle) int wsl::windows::common::socket::Send(
_In_ SOCKET Socket, _In_ gsl::span<const gsl::byte> Buffer, _In_opt_ HANDLE ExitHandle, _In_ const std::source_location& Location)
{ {
OVERLAPPED Overlapped{};
const wil::unique_event OverlappedEvent(wil::EventOptions::ManualReset); const wil::unique_event OverlappedEvent(wil::EventOptions::ManualReset);
WSABUF VectorBuffer = {gsl::narrow_cast<ULONG>(Buffer.size()), const_cast<CHAR*>(reinterpret_cast<const CHAR*>(Buffer.data()))}; OVERLAPPED Overlapped{};
Overlapped.hEvent = OverlappedEvent.get(); Overlapped.hEvent = OverlappedEvent.get();
DWORD BytesWritten{};
if (WSASend(Socket, &VectorBuffer, 1, &BytesWritten, 0, &Overlapped, nullptr) != 0) DWORD Offset = 0;
while (Offset < Buffer.size())
{ {
DWORD Flags; OverlappedEvent.ResetEvent();
std::tie(BytesWritten, Flags) = GetResult(Socket, Overlapped, INFINITE, ExitHandle);
WSABUF VectorBuffer = {
gsl::narrow_cast<ULONG>(Buffer.size() - Offset), const_cast<CHAR*>(reinterpret_cast<const CHAR*>(Buffer.data() + Offset))};
DWORD BytesWritten{};
if (WSASend(Socket, &VectorBuffer, 1, &BytesWritten, 0, &Overlapped, nullptr) != 0)
{
// If WSASend returns non-zero, expect WSA_IO_PENDING.
if (auto error = WSAGetLastError(); error != WSA_IO_PENDING)
{
THROW_WIN32_MSG(error, "WSASend failed. From: %hs", std::format("{}", Location).c_str());
}
DWORD Flags;
std::tie(BytesWritten, Flags) = GetResult(Socket, Overlapped, INFINITE, ExitHandle, Location);
if (BytesWritten == 0)
{
THROW_WIN32_MSG(ERROR_CONNECTION_ABORTED, "Socket closed during WSASend(). From: %hs", std::format("{}", Location).c_str());
}
}
Offset += BytesWritten;
if (Offset < Buffer.size())
{
WSL_LOG("PartialSocketWrite", TraceLoggingValue(Buffer.size(), "MessagSize"), TraceLoggingValue(Offset, "Offset"));
}
} }
WI_ASSERT(BytesWritten == gsl::narrow_cast<DWORD>(Buffer.size())); WI_ASSERT(Offset == gsl::narrow_cast<DWORD>(Buffer.size()));
return BytesWritten; return Offset;
} }

View File

@ -18,16 +18,42 @@ Abstract:
namespace wsl::windows::common::socket { namespace wsl::windows::common::socket {
void Accept(_In_ SOCKET ListenSocket, _In_ SOCKET Socket, _In_ int Timeout, _In_opt_ HANDLE ExitHandle); void Accept(
_In_ SOCKET ListenSocket,
_In_ SOCKET Socket,
_In_ int Timeout,
_In_opt_ HANDLE ExitHandle,
_In_ const std::source_location& Location = std::source_location::current());
std::pair<DWORD, DWORD> GetResult(_In_ SOCKET Socket, _In_ OVERLAPPED& Overlapped, _In_ DWORD Timeout, _In_ HANDLE ExitHandle); std::pair<DWORD, DWORD> GetResult(
_In_ SOCKET Socket, _In_ OVERLAPPED& Overlapped, _In_ DWORD Timeout, _In_ HANDLE ExitHandle, _In_ const std::source_location& Location);
int Receive(_In_ SOCKET Socket, _In_ gsl::span<gsl::byte> Buffer, _In_opt_ HANDLE ExitHandle = nullptr, _In_ DWORD Flags = MSG_WAITALL, _In_ DWORD Timeout = INFINITE); int Receive(
_In_ SOCKET Socket,
_In_ gsl::span<gsl::byte> Buffer,
_In_opt_ HANDLE ExitHandle = nullptr,
_In_ DWORD Flags = MSG_WAITALL,
_In_ DWORD Timeout = INFINITE,
_In_ const std::source_location& Location = std::source_location::current());
std::vector<gsl::byte> Receive(_In_ SOCKET Socket, _In_opt_ HANDLE ExitHandle = nullptr, _In_ DWORD Timeout = INFINITE); std::vector<gsl::byte> Receive(
_In_ SOCKET Socket,
_In_opt_ HANDLE ExitHandle = nullptr,
_In_ DWORD Timeout = INFINITE,
_In_ const std::source_location& Location = std::source_location::current());
int ReceiveNoThrow(_In_ SOCKET Socket, _In_ gsl::span<gsl::byte> Buffer, _In_opt_ HANDLE ExitHandle = nullptr, _In_ DWORD Flags = MSG_WAITALL, _In_ DWORD Timeout = INFINITE); int ReceiveNoThrow(
_In_ SOCKET Socket,
_In_ gsl::span<gsl::byte> Buffer,
_In_opt_ HANDLE ExitHandle = nullptr,
_In_ DWORD Flags = MSG_WAITALL,
_In_ DWORD Timeout = INFINITE,
_In_ const std::source_location& Location = std::source_location::current());
int Send(_In_ SOCKET Socket, _In_ gsl::span<const gsl::byte> Buffer, _In_opt_ HANDLE ExitHandle = nullptr); int Send(
_In_ SOCKET Socket,
_In_ gsl::span<const gsl::byte> Buffer,
_In_opt_ HANDLE ExitHandle = nullptr,
_In_ const std::source_location& Location = std::source_location::current());
} // namespace wsl::windows::common::socket } // namespace wsl::windows::common::socket

View File

@ -141,7 +141,9 @@ static const std::map<HRESULT, LPCWSTR> g_commonErrors{
X_WIN32(ERROR_NO_DATA), X_WIN32(ERROR_NO_DATA),
X_WIN32(WSAETIMEDOUT), X_WIN32(WSAETIMEDOUT),
X_WIN32(ERROR_OPERATION_ABORTED), X_WIN32(ERROR_OPERATION_ABORTED),
X_WIN32(WSAECONNREFUSED)}; X_WIN32(WSAECONNREFUSED),
X_WIN32(ERROR_BAD_PATHNAME),
X(WININET_E_TIMEOUT)};
#undef X #undef X
@ -1392,10 +1394,17 @@ int WINAPI InstallRecordHandler(void* context, UINT messageType, LPCWSTR message
try try
{ {
WSL_LOG("MSIMessage", TraceLoggingValue(messageType, "type"), TraceLoggingValue(message, "message")); WSL_LOG("MSIMessage", TraceLoggingValue(messageType, "type"), TraceLoggingValue(message, "message"));
auto type = (INSTALLMESSAGE)(0xFF000000 & (UINT)messageType);
if (type == INSTALLMESSAGE_ERROR || type == INSTALLMESSAGE_FATALEXIT || type == INSTALLMESSAGE_WARNING)
{
WriteInstallLog(std::format("MSI message: {}", message));
}
auto* callback = reinterpret_cast<const std::function<void(UINT, LPCWSTR)>*>(context); auto* callback = reinterpret_cast<const std::function<void(UINT, LPCWSTR)>*>(context);
if (callback != nullptr) if (callback != nullptr)
{ {
(*callback)((INSTALLMESSAGE)(0xFF000000 & (UINT)messageType), message); (*callback)(type, message);
} }
} }
CATCH_LOG(); CATCH_LOG();
@ -1449,6 +1458,8 @@ int wsl::windows::common::wslutil::UpdatePackage(bool PreRelease, bool Repair)
UINT wsl::windows::common::wslutil::UpgradeViaMsi( UINT wsl::windows::common::wslutil::UpgradeViaMsi(
_In_ LPCWSTR PackageLocation, _In_opt_ LPCWSTR ExtraArgs, _In_opt_ LPCWSTR LogFile, _In_ const std::function<void(INSTALLMESSAGE, LPCWSTR)>& Callback) _In_ LPCWSTR PackageLocation, _In_opt_ LPCWSTR ExtraArgs, _In_opt_ LPCWSTR LogFile, _In_ const std::function<void(INSTALLMESSAGE, LPCWSTR)>& Callback)
{ {
WriteInstallLog(std::format("Upgrading via MSI package: {}. Args: {}", PackageLocation, ExtraArgs != nullptr ? ExtraArgs : L""));
ConfigureMsiLogging(LogFile, Callback); ConfigureMsiLogging(LogFile, Callback);
auto result = MsiInstallProduct(PackageLocation, ExtraArgs); auto result = MsiInstallProduct(PackageLocation, ExtraArgs);
@ -1457,6 +1468,8 @@ UINT wsl::windows::common::wslutil::UpgradeViaMsi(
TraceLoggingValue(result, "result"), TraceLoggingValue(result, "result"),
TraceLoggingValue(ExtraArgs != nullptr ? ExtraArgs : L"", "ExtraArgs")); TraceLoggingValue(ExtraArgs != nullptr ? ExtraArgs : L"", "ExtraArgs"));
WriteInstallLog(std::format("MSI upgrade result: {}", result));
return result; return result;
} }
@ -1465,10 +1478,15 @@ UINT wsl::windows::common::wslutil::UninstallViaMsi(_In_opt_ LPCWSTR LogFile, _I
const auto key = OpenLxssMachineKey(KEY_READ); const auto key = OpenLxssMachineKey(KEY_READ);
const auto productCode = ReadString(key.get(), L"Msi", L"ProductCode", nullptr); const auto productCode = ReadString(key.get(), L"Msi", L"ProductCode", nullptr);
WriteInstallLog(std::format("Uninstalling MSI package: {}", productCode));
ConfigureMsiLogging(LogFile, Callback); ConfigureMsiLogging(LogFile, Callback);
auto result = MsiConfigureProduct(productCode.c_str(), 0, INSTALLSTATE_ABSENT); auto result = MsiConfigureProduct(productCode.c_str(), 0, INSTALLSTATE_ABSENT);
WSL_LOG("MsiUninstallResult", TraceLoggingValue(result, "result")); WSL_LOG("MsiUninstallResult", TraceLoggingValue(result, "result"));
WriteInstallLog(std::format("MSI package uninstall result: {}", result));
return result; return result;
} }
@ -1499,6 +1517,43 @@ wil::unique_hfile wsl::windows::common::wslutil::ValidateFileSignature(LPCWSTR P
return fileHandle; return fileHandle;
} }
void wsl::windows::common::wslutil::WriteInstallLog(const std::string& Content)
try
{
static std::wstring path = wil::GetWindowsDirectoryW<std::wstring>() + L"\\temp\\wsl-install-log.txt";
// Wait up to 10 seconds for the log file mutex
wil::unique_handle mutex{CreateMutex(nullptr, true, L"Global\\WslInstallLog")};
THROW_LAST_ERROR_IF(!mutex);
THROW_LAST_ERROR_IF(WaitForSingleObject(mutex.get(), 10 * 1000) != WAIT_OBJECT_0);
wil::unique_handle file{CreateFile(
path.c_str(), GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_ALWAYS, 0, nullptr)};
THROW_LAST_ERROR_IF(!file);
LARGE_INTEGER size{};
THROW_IF_WIN32_BOOL_FALSE(GetFileSizeEx(file.get(), &size));
// Append to the file if its size is below 10MB, otherwise truncate.
if (size.QuadPart < 10 * _1MB)
{
THROW_LAST_ERROR_IF(SetFilePointer(file.get(), 0, nullptr, FILE_END) == INVALID_SET_FILE_POINTER);
}
else
{
THROW_IF_WIN32_BOOL_FALSE(SetEndOfFile(file.get()));
}
static auto processName = wil::GetModuleFileNameW<std::wstring>();
auto logLine = std::format("{:%FT%TZ} {}[{}]: {}\n", std::chrono::system_clock::now(), processName, WSL_PACKAGE_VERSION, Content);
DWORD bytesWritten{};
THROW_IF_WIN32_BOOL_FALSE(WriteFile(file.get(), logLine.c_str(), static_cast<DWORD>(logLine.size()), &bytesWritten, nullptr));
}
CATCH_LOG();
winrt::Windows::Management::Deployment::PackageVolume wsl::windows::common::wslutil::GetSystemVolume() winrt::Windows::Management::Deployment::PackageVolume wsl::windows::common::wslutil::GetSystemVolume()
try try
{ {

View File

@ -187,6 +187,8 @@ UINT UpgradeViaMsi(_In_ LPCWSTR PackageLocation, _In_opt_ LPCWSTR ExtraArgs, _In
UINT UninstallViaMsi(_In_opt_ LPCWSTR LogFile, _In_ const std::function<void(INSTALLMESSAGE, LPCWSTR)>& callback); UINT UninstallViaMsi(_In_opt_ LPCWSTR LogFile, _In_ const std::function<void(INSTALLMESSAGE, LPCWSTR)>& callback);
void WriteInstallLog(const std::string& Content);
winrt::Windows::Management::Deployment::PackageVolume GetSystemVolume(); winrt::Windows::Management::Deployment::PackageVolume GetSystemVolume();
} // namespace wsl::windows::common::wslutil } // namespace wsl::windows::common::wslutil

View File

@ -551,7 +551,9 @@ wil::unique_handle LxssInstance::_CreateLxProcess(
m_oobeThread = std::thread([this, OobeMessagePort = std::move(OobeMessagePort), registration = std::move(registration)]() mutable { m_oobeThread = std::thread([this, OobeMessagePort = std::move(OobeMessagePort), registration = std::move(registration)]() mutable {
try try
{ {
auto Message = OobeMessagePort->Receive(); // N.B. The LX_INIT_OOBE_RESULT message is only sent once the OOBE process completes, which might be waiting on user input.
// Do no set a timeout here otherwise the OOBE flow will fail if the OOBE process takes longer than expected.
auto Message = OobeMessagePort->Receive(INFINITE);
auto* OobeResult = gslhelpers::try_get_struct<LX_INIT_OOBE_RESULT>(gsl::make_span(Message)); auto* OobeResult = gslhelpers::try_get_struct<LX_INIT_OOBE_RESULT>(gsl::make_span(Message));
THROW_HR_IF(E_INVALIDARG, !OobeResult || (OobeResult->Header.MessageType != LxInitOobeResult)); THROW_HR_IF(E_INVALIDARG, !OobeResult || (OobeResult->Header.MessageType != LxInitOobeResult));

View File

@ -510,7 +510,7 @@ try
const auto session = m_session.lock(); const auto session = m_session.lock();
RETURN_HR_IF(RPC_E_DISCONNECTED, !session); RETURN_HR_IF(RPC_E_DISCONNECTED, !session);
return session->Shutdown(false, Force); return session->Shutdown(false, Force ? ShutdownBehavior::Force : ShutdownBehavior::Wait);
} }
CATCH_RETURN() CATCH_RETURN()
@ -1926,7 +1926,7 @@ HRESULT LxssUserSessionImpl::SetVersion(_In_ LPCGUID DistroGuid, _In_ ULONG Vers
if (m_utilityVm->GetConfig().SetVersionDebug) if (m_utilityVm->GetConfig().SetVersionDebug)
{ {
commandLine += " -v"; commandLine += " -vv --totals";
} }
// Run the bsdtar elf binary expand the tar file using the socket as stdin. // Run the bsdtar elf binary expand the tar file using the socket as stdin.
@ -1991,7 +1991,7 @@ HRESULT LxssUserSessionImpl::SetVersion(_In_ LPCGUID DistroGuid, _In_ ULONG Vers
if (m_utilityVm->GetConfig().SetVersionDebug) if (m_utilityVm->GetConfig().SetVersionDebug)
{ {
commandLine += " -v"; commandLine += " -vv --totals";
} }
// Run the bsdtar elf binary to create the tar file using the socket as stdout. // Run the bsdtar elf binary to create the tar file using the socket as stdout.
@ -2052,13 +2052,11 @@ HRESULT LxssUserSessionImpl::SetVersion(_In_ LPCGUID DistroGuid, _In_ ULONG Vers
return result; return result;
} }
HRESULT LxssUserSessionImpl::Shutdown(_In_ bool PreventNewInstances, bool ForceTerminate) HRESULT LxssUserSessionImpl::Shutdown(_In_ bool PreventNewInstances, ShutdownBehavior Behavior)
{ {
try try
{ {
// If the user asks for a forced termination, kill the VM auto forceTerminate = [this]() {
if (ForceTerminate)
{
auto vmId = m_vmId.load(); auto vmId = m_vmId.load();
if (!IsEqualGUID(vmId, GUID_NULL)) if (!IsEqualGUID(vmId, GUID_NULL))
{ {
@ -2071,11 +2069,43 @@ HRESULT LxssUserSessionImpl::Shutdown(_In_ bool PreventNewInstances, bool ForceT
WSL_LOG("ForceTerminateVm", TraceLoggingValue(result, "Result")); WSL_LOG("ForceTerminateVm", TraceLoggingValue(result, "Result"));
} }
};
// If the user asks for a forced termination, kill the VM
if (Behavior == ShutdownBehavior::Force)
{
forceTerminate();
} }
{ {
bool locked = false;
auto unlock = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [this, &locked]() {
if (locked)
{
m_instanceLock.unlock();
}
});
if (Behavior == ShutdownBehavior::ForceAfter30Seconds)
{
if (m_instanceLock.try_lock_for(std::chrono::seconds(30)))
{
locked = true;
}
else
{
WSL_LOG("VmShutdownLockTimedOut");
forceTerminate();
}
}
if (!locked)
{
m_instanceLock.lock();
locked = true;
}
// Stop each instance with the lock held. // Stop each instance with the lock held.
std::lock_guard lock(m_instanceLock);
while (!m_runningInstances.empty()) while (!m_runningInstances.empty())
{ {
_TerminateInstanceInternal(&m_runningInstances.begin()->first, false); _TerminateInstanceInternal(&m_runningInstances.begin()->first, false);
@ -2776,8 +2806,6 @@ void LxssUserSessionImpl::_CreateVm()
// Create the utility VM and register for callbacks. // Create the utility VM and register for callbacks.
m_utilityVm = WslCoreVm::Create(m_userToken, std::move(config), vmId); m_utilityVm = WslCoreVm::Create(m_userToken, std::move(config), vmId);
m_utilityVm->GetRuntimeId();
if (m_httpProxyStateTracker) if (m_httpProxyStateTracker)
{ {
// this needs to be done after the VM has finished in case we fell back to NAT mode // this needs to be done after the VM has finished in case we fell back to NAT mode
@ -2786,30 +2814,6 @@ void LxssUserSessionImpl::_CreateVm()
try try
{ {
auto callback = [this](auto Pid) {
// If the vm is currently being destroyed, the instance lock might be held
// while WslCoreVm's destructor is waiting on this thread.
// Cancel the call if the vm destruction is signaled.
// Note: This is safe because m_instanceLock is always initialized
// and because WslCoreVm's destructor waits for this thread, the session can't be gone
// until this callback completes.
auto lock = m_instanceLock.try_lock();
while (!lock)
{
if (m_vmTerminating.wait(100))
{
return;
}
lock = m_instanceLock.try_lock();
}
auto unlock = wil::scope_exit([&]() { m_instanceLock.unlock(); });
TerminateByClientIdLockHeld(Pid);
};
m_utilityVm->RegisterCallbacks(std::bind(callback, _1), std::bind(s_VmTerminated, this, _1));
// Mount disks after the system distro vhd is mounted in case filesystem detection is needed. // Mount disks after the system distro vhd is mounted in case filesystem detection is needed.
_LoadDiskMounts(); _LoadDiskMounts();
@ -2841,6 +2845,34 @@ void LxssUserSessionImpl::_CreateVm()
_VmTerminate(); _VmTerminate();
throw; throw;
} }
auto callback = [this](auto Pid) {
// If the vm is currently being destroyed, the instance lock might be held
// while WslCoreVm's destructor is waiting on this thread.
// Cancel the call if the vm destruction is signaled.
// Note: This is safe because m_instanceLock is always initialized
// and because WslCoreVm's destructor waits for this thread, the session can't be gone
// until this callback completes.
auto lock = m_instanceLock.try_lock();
while (!lock)
{
if (m_vmTerminating.wait(100))
{
return;
}
lock = m_instanceLock.try_lock();
}
auto unlock = wil::scope_exit([&]() { m_instanceLock.unlock(); });
TerminateByClientIdLockHeld(Pid);
};
// N.B. The callbacks must be registered outside of the above try/catch.
// Otherwise if an exception is thrown, calling _VmTerminate() will trigger the 's_VmTerminated' termination callback
// Which can deadlock since this thread holds the instance lock and HCS can block until the VM termination callback returns before deleting the VM.
m_utilityVm->RegisterCallbacks(std::bind(callback, _1), std::bind(s_VmTerminated, this, _1));
} }
_VmCheckIdle(); _VmCheckIdle();

View File

@ -54,6 +54,13 @@ typedef struct _LXSS_VM_MODE_SETUP_CONTEXT
std::shared_ptr<LxssRunningInstance> instance; std::shared_ptr<LxssRunningInstance> instance;
} LXSS_VM_MODE_SETUP_CONTEXT, *PLXSS_VM_MODE_SETUP_CONTEXT; } LXSS_VM_MODE_SETUP_CONTEXT, *PLXSS_VM_MODE_SETUP_CONTEXT;
enum class ShutdownBehavior
{
Wait,
Force,
ForceAfter30Seconds
};
/// <summary> /// <summary>
/// Each COM client gets a unique LxssUserSession object which contains a std::weak_ptr to a LxssUserSessionImpl for that user. /// Each COM client gets a unique LxssUserSession object which contains a std::weak_ptr to a LxssUserSessionImpl for that user.
/// </summary> /// </summary>
@ -491,7 +498,7 @@ public:
/// <summary> /// <summary>
/// Terminates all running instances and the Linux utility vm. /// Terminates all running instances and the Linux utility vm.
/// </summary> /// </summary>
HRESULT Shutdown(_In_ bool PreventNewInstances = false, _In_ bool ForceTerminate = false); HRESULT Shutdown(_In_ bool PreventNewInstances = false, ShutdownBehavior Behavior = ShutdownBehavior::Wait);
/// <summary> /// <summary>
/// Worker thread for logging telemetry about processes running inside of WSL. /// Worker thread for logging telemetry about processes running inside of WSL.
@ -784,7 +791,7 @@ private:
/// <summary> /// <summary>
/// Lock for protecting various lists. /// Lock for protecting various lists.
/// </summary> /// </summary>
std::recursive_mutex m_instanceLock; std::recursive_timed_mutex m_instanceLock;
/// <summary> /// <summary>
/// Contains the currently running utility VM's. /// Contains the currently running utility VM's.

View File

@ -49,7 +49,7 @@ void ClearSessionsAndBlockNewInstancesLockHeld(std::optional<std::vector<std::sh
// since that could lead to a deadlock if FindSessionByCookie is called since that would try to lock g_sessionLock // since that could lead to a deadlock if FindSessionByCookie is called since that would try to lock g_sessionLock
// while holding the session inner lock // while holding the session inner lock
session->Shutdown(true); session->Shutdown(true, ShutdownBehavior::ForceAfter30Seconds);
} }
sessions.reset(); sessions.reset();

View File

@ -375,13 +375,6 @@ void WslCoreInstance::Initialize()
drvfsMount = m_initializeDrvFs(m_userToken.get()); drvfsMount = m_initializeDrvFs(m_userToken.get());
} }
// If not using the WSL init, initialization is complete.
if (WI_IsFlagSet(m_configuration.Flags, LXSS_DISTRO_FLAGS_WSLCORE_MODE))
{
m_initialized = true;
return;
}
// Create a console manager that will be used to manage session leaders. // Create a console manager that will be used to manage session leaders.
m_consoleManager = ConsoleManager::CreateConsoleManager(m_initChannel); m_consoleManager = ConsoleManager::CreateConsoleManager(m_initChannel);
@ -477,8 +470,12 @@ bool WslCoreInstance::RequestStop(_In_ bool Force)
terminateMessage.Header.MessageSize = sizeof(terminateMessage); terminateMessage.Header.MessageSize = sizeof(terminateMessage);
terminateMessage.Force = Force; terminateMessage.Force = Force;
const auto& terminateResponse = m_initChannel->GetChannel().Transaction(terminateMessage, nullptr, m_socketTimeout); m_initChannel->GetChannel().SendMessage(terminateMessage);
shutdown = terminateResponse.Result; auto [message, span] = m_initChannel->GetChannel().ReceiveMessageOrClosed<RESULT_MESSAGE<bool>>(m_socketTimeout);
if (message)
{
shutdown = message->Result;
}
} }
CATCH_LOG() CATCH_LOG()

View File

@ -872,9 +872,10 @@ WslCoreVm::~WslCoreVm() noexcept
WSL_LOG("TerminateVmStop"); WSL_LOG("TerminateVmStop");
} }
wil::unique_socket WslCoreVm::AcceptConnection(_In_ DWORD ReceiveTimeout) const wil::unique_socket WslCoreVm::AcceptConnection(_In_ DWORD ReceiveTimeout, _In_ const std::source_location& Location) const
{ {
auto socket = wsl::windows::common::hvsocket::Accept(m_listenSocket.get(), m_vmConfig.KernelBootTimeout, m_terminatingEvent.get()); auto socket =
wsl::windows::common::hvsocket::Accept(m_listenSocket.get(), m_vmConfig.KernelBootTimeout, m_terminatingEvent.get(), Location);
if (ReceiveTimeout != 0) if (ReceiveTimeout != 0)
{ {
THROW_LAST_ERROR_IF(setsockopt(socket.get(), SOL_SOCKET, SO_RCVTIMEO, (const char*)&ReceiveTimeout, sizeof(ReceiveTimeout)) == SOCKET_ERROR); THROW_LAST_ERROR_IF(setsockopt(socket.get(), SOL_SOCKET, SO_RCVTIMEO, (const char*)&ReceiveTimeout, sizeof(ReceiveTimeout)) == SOCKET_ERROR);

View File

@ -61,7 +61,7 @@ public:
~WslCoreVm() noexcept; ~WslCoreVm() noexcept;
wil::unique_socket AcceptConnection(_In_ DWORD ReceiveTimeout = 0) const; wil::unique_socket AcceptConnection(_In_ DWORD ReceiveTimeout = 0, _In_ const std::source_location& Location = std::source_location::current()) const;
enum class DiskType enum class DiskType
{ {

View File

@ -103,9 +103,8 @@ cpp_quote("#define LXSS_DISTRO_FLAGS_ENABLE_INTEROP 0x1")
cpp_quote("#define LXSS_DISTRO_FLAGS_APPEND_NT_PATH 0x2") cpp_quote("#define LXSS_DISTRO_FLAGS_APPEND_NT_PATH 0x2")
cpp_quote("#define LXSS_DISTRO_FLAGS_ENABLE_DRIVE_MOUNTING 0x4") cpp_quote("#define LXSS_DISTRO_FLAGS_ENABLE_DRIVE_MOUNTING 0x4")
cpp_quote("#define LXSS_DISTRO_FLAGS_VM_MODE 0x8") cpp_quote("#define LXSS_DISTRO_FLAGS_VM_MODE 0x8")
cpp_quote("#define LXSS_DISTRO_FLAGS_WSLCORE_MODE 0x10")
cpp_quote("#define LXSS_DISTRO_FLAGS_UNCHANGED 0xFFFFFFFE") // Not using ~0 since the inbox tests use that value to validate that invalid flags return an error. cpp_quote("#define LXSS_DISTRO_FLAGS_UNCHANGED 0xFFFFFFFE") // Not using ~0 since the inbox tests use that value to validate that invalid flags return an error.
cpp_quote("#define LXSS_DISTRO_FLAGS_ALL (LXSS_DISTRO_FLAGS_ENABLE_INTEROP | LXSS_DISTRO_FLAGS_APPEND_NT_PATH | LXSS_DISTRO_FLAGS_ENABLE_DRIVE_MOUNTING | LXSS_DISTRO_FLAGS_VM_MODE| LXSS_DISTRO_FLAGS_WSLCORE_MODE)") cpp_quote("#define LXSS_DISTRO_FLAGS_ALL (LXSS_DISTRO_FLAGS_ENABLE_INTEROP | LXSS_DISTRO_FLAGS_APPEND_NT_PATH | LXSS_DISTRO_FLAGS_ENABLE_DRIVE_MOUNTING | LXSS_DISTRO_FLAGS_VM_MODE)")
cpp_quote("#define LXSS_DISTRO_FLAGS_DEFAULT (LXSS_DISTRO_FLAGS_ENABLE_INTEROP | LXSS_DISTRO_FLAGS_APPEND_NT_PATH | LXSS_DISTRO_FLAGS_ENABLE_DRIVE_MOUNTING)") cpp_quote("#define LXSS_DISTRO_FLAGS_DEFAULT (LXSS_DISTRO_FLAGS_ENABLE_INTEROP | LXSS_DISTRO_FLAGS_APPEND_NT_PATH | LXSS_DISTRO_FLAGS_ENABLE_DRIVE_MOUNTING)")
cpp_quote("#define LXSS_ENUMERATE_FLAGS_DEFAULT 0x1") cpp_quote("#define LXSS_ENUMERATE_FLAGS_DEFAULT 0x1")

View File

@ -23,6 +23,7 @@ Abstract:
using unique_msi_handle = wil::unique_any<MSIHANDLE, decltype(MsiCloseHandle), &MsiCloseHandle>; using unique_msi_handle = wil::unique_any<MSIHANDLE, decltype(MsiCloseHandle), &MsiCloseHandle>;
using namespace wsl::windows::common::registry; using namespace wsl::windows::common::registry;
using namespace wsl::windows::common::wslutil;
static constexpr auto c_progIdPrefix{L"App."}; static constexpr auto c_progIdPrefix{L"App."};
static constexpr auto c_protocolProgIdSuffix{L".Protocol"}; static constexpr auto c_protocolProgIdSuffix{L".Protocol"};
@ -519,6 +520,7 @@ extern "C" UINT __stdcall DeprovisionMsix(MSIHANDLE install)
try try
{ {
WSL_LOG("DeprovisionMsix"); WSL_LOG("DeprovisionMsix");
WriteInstallLog("MSI install: DeprovisionMsix");
const winrt::Windows::Management::Deployment::PackageManager packageManager; const winrt::Windows::Management::Deployment::PackageManager packageManager;
const auto result = packageManager.DeprovisionPackageForAllUsersAsync(wsl::windows::common::wslutil::c_msixPackageFamilyName).get(); const auto result = packageManager.DeprovisionPackageForAllUsersAsync(wsl::windows::common::wslutil::c_msixPackageFamilyName).get();
@ -542,6 +544,7 @@ extern "C" UINT __stdcall RemoveMsixAsSystem(MSIHANDLE install)
try try
{ {
WSL_LOG("RemoveMsixAsSystem"); WSL_LOG("RemoveMsixAsSystem");
WriteInstallLog("MSI install: RemoveMsixAsSystem");
const winrt::Windows::Management::Deployment::PackageManager packageManager; const winrt::Windows::Management::Deployment::PackageManager packageManager;
@ -571,6 +574,7 @@ extern "C" UINT __stdcall RemoveMsixAsUser(MSIHANDLE install)
try try
{ {
WSL_LOG("RemoveMsixAsUser"); WSL_LOG("RemoveMsixAsUser");
WriteInstallLog("MSI install: RemoveMsixAsUser");
const winrt::Windows::Management::Deployment::PackageManager packageManager; const winrt::Windows::Management::Deployment::PackageManager packageManager;
@ -640,6 +644,7 @@ extern "C" UINT __stdcall InstallMsixAsUser(MSIHANDLE install)
try try
{ {
WSL_LOG("InstallMsixAsUser"); WSL_LOG("InstallMsixAsUser");
WriteInstallLog("MSI install: InstallMsixAsUser");
// RegisterPackageByFamilyNameAsync() cannot be run as SYSTEM. // RegisterPackageByFamilyNameAsync() cannot be run as SYSTEM.
// If this thread runs as SYSTEM, simply skip this step. // If this thread runs as SYSTEM, simply skip this step.
@ -683,6 +688,7 @@ try
msixFile.Handle.reset(); msixFile.Handle.reset();
WSL_LOG("InstallMsix", TraceLoggingValue(msixFile.Path.c_str(), "Path")); WSL_LOG("InstallMsix", TraceLoggingValue(msixFile.Path.c_str(), "Path"));
WriteInstallLog("MSI install: InstallMsix");
winrt::Windows::Management::Deployment::PackageManager packageManager; winrt::Windows::Management::Deployment::PackageManager packageManager;
@ -780,11 +786,25 @@ catch (...)
return ERROR_INSTALL_FAILURE; return ERROR_INSTALL_FAILURE;
} }
extern "C" UINT __stdcall WslFinalizeInstallation(MSIHANDLE install)
{
try
{
WSL_LOG("WslFinalizeInstallation");
WriteInstallLog(std::format("MSI install: WslFinalizeInstallation"));
}
CATCH_LOG();
return NOERROR;
}
extern "C" UINT __stdcall WslValidateInstallation(MSIHANDLE install) extern "C" UINT __stdcall WslValidateInstallation(MSIHANDLE install)
try try
{ {
WSL_LOG("WslValidateInstallation"); WSL_LOG("WslValidateInstallation");
WriteInstallLog(std::format("MSI install: WslValidateInstallation"));
// TODO: Use a more precise version check so we don't install if the Windows build doesn't support lifted. // TODO: Use a more precise version check so we don't install if the Windows build doesn't support lifted.
if (wsl::windows::common::helpers::GetWindowsVersion().BuildNumber < wsl::windows::common::helpers::Vibranium) if (wsl::windows::common::helpers::GetWindowsVersion().BuildNumber < wsl::windows::common::helpers::Vibranium)

View File

@ -5,6 +5,7 @@ EXPORTS
CleanMsixState CleanMsixState
DeprovisionMsix DeprovisionMsix
WslValidateInstallation WslValidateInstallation
WslFinalizeInstallation
InstallMsix InstallMsix
InstallMsixAsUser InstallMsixAsUser
RegisterLspCategories RegisterLspCategories

View File

@ -102,7 +102,7 @@ DWORD WINAPI InstallMsiPackage(LPVOID Context)
return 0; return 0;
} }
bool IsUpdateNeeded() std::pair<bool, std::wstring> IsUpdateNeeded()
{ {
try try
{ {
@ -115,13 +115,15 @@ bool IsUpdateNeeded()
TraceLoggingLevel(WINEVENT_LEVEL_INFO), TraceLoggingLevel(WINEVENT_LEVEL_INFO),
TraceLoggingValue(installedVersion.c_str(), "InstalledVersion")); TraceLoggingValue(installedVersion.c_str(), "InstalledVersion"));
return installedVersion.empty() || wsl::windows::common::wslutil::ParseWslPackageVersion(installedVersion) < wsl::shared::PackageVersion; return std::make_pair(
installedVersion.empty() || wsl::windows::common::wslutil::ParseWslPackageVersion(installedVersion) < wsl::shared::PackageVersion,
installedVersion);
} }
catch (...) catch (...)
{ {
LOG_CAUGHT_EXCEPTION(); LOG_CAUGHT_EXCEPTION();
return false; return std::make_pair(false, L"");
} }
} }
@ -132,11 +134,14 @@ std::shared_ptr<InstallContext> LaunchInstall()
auto lock = mutex.lock_exclusive(); auto lock = mutex.lock_exclusive();
if (!IsUpdateNeeded()) auto [updateNeeded, existingVersion] = IsUpdateNeeded();
if (!updateNeeded)
{ {
return {}; return {};
} }
wsl::windows::common::wslutil::WriteInstallLog(std::format("Starting upgrade via WslInstaller. Previous version: {}", existingVersion));
// Return an existing install if any // Return an existing install if any
if (auto ptr = weak_context.lock(); ptr != nullptr) if (auto ptr = weak_context.lock(); ptr != nullptr)
{ {

View File

@ -110,7 +110,7 @@ class SimpleTests
L"The operation completed successfully. \r\n", L"The operation completed successfully. \r\n",
L"wsl: Sparse VHD support is currently disabled due to potential data corruption.\r\n" L"wsl: Sparse VHD support is currently disabled due to potential data corruption.\r\n"
L"To force a distribution to use a sparse vhd, please run:\r\n" L"To force a distribution to use a sparse vhd, please run:\r\n"
L"wsl.exe --manage <DistributionName> --set-sparse --allow-unsafe\r\n", L"wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe\r\n",
0); 0);
std::filesystem::path vhdPath = vhdDir / LXSS_VM_MODE_VHD_NAME; std::filesystem::path vhdPath = vhdDir / LXSS_VM_MODE_VHD_NAME;
@ -123,7 +123,7 @@ class SimpleTests
std::format(L"{} {} {} {}", WSL_MANAGE_ARG, tempDistro, WSL_MANAGE_ARG_SET_SPARSE_OPTION_LONG, L"true").c_str(), std::format(L"{} {} {} {}", WSL_MANAGE_ARG, tempDistro, WSL_MANAGE_ARG_SET_SPARSE_OPTION_LONG, L"true").c_str(),
L"Sparse VHD support is currently disabled due to potential data corruption.\r\n" L"Sparse VHD support is currently disabled due to potential data corruption.\r\n"
L"To force a distribution to use a sparse vhd, please run:\r\n" L"To force a distribution to use a sparse vhd, please run:\r\n"
L"wsl.exe --manage <DistributionName> --set-sparse --allow-unsafe\r\nError code: Wsl/Service/E_INVALIDARG\r\n", L"wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe\r\nError code: Wsl/Service/E_INVALIDARG\r\n",
L"", L"",
-1); -1);

View File

@ -5326,6 +5326,76 @@ Error code: Wsl/InstallDistro/WSL_E_INVALID_JSON\r\n",
VERIFY_ARE_EQUAL(error, L""); VERIFY_ARE_EQUAL(error, L"");
} }
// Validate that manifest distribution ordering is preserved.
{
auto validateOrder = [](const std::vector<LPCWSTR>& expected) {
auto [out, _] = LxsstuLaunchWslAndCaptureOutput(L"--list --online");
auto lines = wsl::shared::string::Split<wchar_t>(out, '\n');
for (size_t i = 0; i < expected.size(); i++)
{
auto end = lines[i + 4].find_first_of(L" \t");
VERIFY_ARE_NOT_EQUAL(end, std::wstring::npos);
auto distro = lines[i + 4].substr(0, end);
VERIFY_ARE_EQUAL(expected[i], distro);
}
};
{
auto manifest =
R"({
"ModernDistributions": {
"distro1": [
{
"Name": "distro1",
"FriendlyName": "distro1Name",
"Amd64Url": {"Url": "","Sha256": ""}
}
],
"distro2": [
{
"Name": "distro2",
"FriendlyName": "distro2Name",
"Amd64Url": {"Url": "","Sha256": ""}
}
]
}
})";
auto restore = SetManifest(manifest);
validateOrder({L"distro1", L"distro2"});
}
{
auto manifest =
R"({
"ModernDistributions": {
"distro2": [
{
"Name": "distro2",
"FriendlyName": "distro2Name",
"Amd64Url": {"Url": "","Sha256": ""}
}
],
"distro1": [
{
"Name": "distro1",
"FriendlyName": "distro1Name",
"Amd64Url": {"Url": "","Sha256": ""}
}
]
}
})";
auto restore = SetManifest(manifest);
validateOrder({L"distro2", L"distro1"});
}
}
} }
TEST_METHOD(ModernInstallEndToEnd) TEST_METHOD(ModernInstallEndToEnd)
@ -6080,6 +6150,9 @@ Error code: Wsl/InstallDistro/WSL_E_INVALID_JSON\r\n",
auto cleanup = auto cleanup =
wil::scope_exit_log(WI_DIAGNOSTICS_INFO, []() { LxsstuLaunchWsl(std::format(L"--unregister {}", test_distro)); }); wil::scope_exit_log(WI_DIAGNOSTICS_INFO, []() { LxsstuLaunchWsl(std::format(L"--unregister {}", test_distro)); });
// The below logline makes it easier to find the bsdtar output when debugging this test case.
fprintf(stderr, "Starting ImportExportStdout test case\n");
auto commandLine = std::format(L"cmd.exe /c wsl --export {} - | wsl --import {} . -", LXSS_DISTRO_NAME_TEST_L, test_distro); auto commandLine = std::format(L"cmd.exe /c wsl --export {} - | wsl --import {} . -", LXSS_DISTRO_NAME_TEST_L, test_distro);
VERIFY_ARE_EQUAL(LxsstuRunCommand(commandLine.data()), 0L); VERIFY_ARE_EQUAL(LxsstuRunCommand(commandLine.data()), 0L);
@ -6147,5 +6220,61 @@ Error code: Wsl/InstallDistro/WSL_E_INVALID_JSON\r\n",
VERIFY_ARE_EQUAL(err, L""); VERIFY_ARE_EQUAL(err, L"");
} }
TEST_METHOD(WslDebug)
{
WSL2_TEST_ONLY();
// Verify that hvsocket debug events are logged to dmesg.
WslConfigChange config(LxssGenerateTestConfig({.kernelCommandLine = L"WSL_DEBUG=hvsocket"}));
VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"dmesg | grep -iF 'vmbus_send_tl_connect_request'"), 0L);
}
TEST_METHOD(CGroupv1)
{
WSL2_TEST_ONLY();
auto expectedMount = [](const char* path, const wchar_t* expected) {
auto [out, _] = LxsstuLaunchWslAndCaptureOutput(std::format(L"findmnt -ln '{}' || true", path));
VERIFY_ARE_EQUAL(out, expected);
};
// Validate that cgroupv2 is mounted by default.
expectedMount("/sys/fs/cgroup", L"/sys/fs/cgroup cgroup2 cgroup2 rw,nosuid,nodev,noexec,relatime,nsdelegate\n");
// Validate that setting cgroup=v1 causes unified cgroups to be mounted.
DistroFileChange wslConf(L"/etc/wsl.conf", false);
wslConf.SetContent(L"[automount]\ncgroups=v1");
TerminateDistribution();
expectedMount(
"/sys/fs/cgroup/unified", L"/sys/fs/cgroup/unified cgroup2 cgroup2 rw,nosuid,nodev,noexec,relatime,nsdelegate\n");
// Validate that the cgroupv1 mounts are present.
expectedMount("/sys/fs/cgroup/cpu", L"/sys/fs/cgroup/cpu cgroup cgroup rw,nosuid,nodev,noexec,relatime,cpu\n");
// Validate that having cgroup_no_v1=all causes the distribution to fall back to v2.
WslConfigChange wslConfig(LxssGenerateTestConfig({.kernelCommandLine = L"cgroup_no_v1=all"}));
expectedMount("/sys/fs/cgroup/unified", L"");
expectedMount("/sys/fs/cgroup", L"/sys/fs/cgroup cgroup2 cgroup2 rw,nosuid,nodev,noexec,relatime,nsdelegate\n");
auto [dmesg, __] = LxsstuLaunchWslAndCaptureOutput(L"dmesg");
VERIFY_ARE_NOT_EQUAL(
dmesg.find(
L"Distribution has cgroupv1 enabled, but kernel command line has cgroup_no_v1=all. Falling back to cgroupv2"),
std::wstring::npos);
}
TEST_METHOD(InitPermissions)
{
WSL2_TEST_ONLY();
auto [out, _] = LxsstuLaunchWslAndCaptureOutput(L"stat -c %a /init");
VERIFY_ARE_EQUAL(out, L"755\n");
}
}; // namespace UnitTests }; // namespace UnitTests
} // namespace UnitTests } // namespace UnitTests

View File

@ -40,7 +40,7 @@ use constant TRAILER => "TRAILER!!!";
# like initramfs. # like initramfs.
# #
use constant INODE => 0; use constant INODE => 0;
use constant MODE => oct("100777"); use constant MODE => oct("100755");
use constant UID => 0; use constant UID => 0;
use constant GID => 0; use constant GID => 0;
use constant NLINK => 0; use constant NLINK => 0;

View File

@ -211,6 +211,15 @@ rules:
capture: capture:
field1: error field1: error
- logline:
provider: Microsoft.Windows.Lxss.Manager
task: LinuxCrash
set:
name: linux-crash
capture:
field3: linux-crash-path
field6: linux-crash-process
- logline: - logline:
provider: Microsoft.Windows.Lxss.Manager provider: Microsoft.Windows.Lxss.Manager
set: wsl-service-logs set: wsl-service-logs
@ -256,6 +265,11 @@ actions:
debug_message: 'Detected user visible error: $error' debug_message: 'Detected user visible error: $error'
skip_similar_issues: false skip_similar_issues: false
- foreach:
var: linux-crash
debug_message: 'Found evidence of linux crash: $linux-crash-process (dump: $linux-crash-path)'
skip_similar_issues: false
- foreach: - foreach:
var: disk-attach-error var: disk-attach-error
debug_message: 'Found evidence of disk failing to attach. Error: $error, Path: $vhdpath' debug_message: 'Found evidence of disk failing to attach. Error: $error, Path: $vhdpath'