Fix potential service deadlock when plugin returns an error from OnVmStarted (#13569)
Blue committed
Oct 8, 2025 at 15:40 UTC
5d097195faf0e2500863c86d50fbc10d2cd604dc
1 file changed
+28
-24
src/windows/service/exe/LxssUserSession.cpp
+28
-24
@@ -2814,30 +2814,6 @@ void LxssUserSessionImpl::_CreateVm()
2814
2815
try
2816
{
2817
- auto callback = [this](auto Pid) {
2818
- // If the vm is currently being destroyed, the instance lock might be held
2819
- // while WslCoreVm's destructor is waiting on this thread.
2820
- // Cancel the call if the vm destruction is signaled.
2821
- // Note: This is safe because m_instanceLock is always initialized
2822
- // and because WslCoreVm's destructor waits for this thread, the session can't be gone
2823
- // until this callback completes.
2824
-
2825
- auto lock = m_instanceLock.try_lock();
2826
- while (!lock)
2827
- {
2828
- if (m_vmTerminating.wait(100))
2829
- {
2830
- return;
2831
- }
2832
- lock = m_instanceLock.try_lock();
2833
- }
2834
-
2835
- auto unlock = wil::scope_exit([&]() { m_instanceLock.unlock(); });
2836
- TerminateByClientIdLockHeld(Pid);
2837
- };
2838
-
2839
- m_utilityVm->RegisterCallbacks(std::bind(callback, _1), std::bind(s_VmTerminated, this, _1));
2840
-
2817
// Mount disks after the system distro vhd is mounted in case filesystem detection is needed.
2818
_LoadDiskMounts();
2819
@@ -2869,6 +2845,34 @@ void LxssUserSessionImpl::_CreateVm()
2845
_VmTerminate();
2846
throw;
2847
}
2848
+
2849
+ auto callback = [this](auto Pid) {
2850
+ // If the vm is currently being destroyed, the instance lock might be held
2851
+ // while WslCoreVm's destructor is waiting on this thread.
2852
+ // Cancel the call if the vm destruction is signaled.
2853
+ // Note: This is safe because m_instanceLock is always initialized
2854
+ // and because WslCoreVm's destructor waits for this thread, the session can't be gone
2855
+ // until this callback completes.
2856
+
2857
+ auto lock = m_instanceLock.try_lock();
2858
+ while (!lock)
2859
+ {
2860
+ if (m_vmTerminating.wait(100))
2861
+ {
2862
+ return;
2863
+ }
2864
+ lock = m_instanceLock.try_lock();
2865
+ }
2866
+
2867
+ auto unlock = wil::scope_exit([&]() { m_instanceLock.unlock(); });
2868
+ TerminateByClientIdLockHeld(Pid);
2869
+ };
2870
+
2871
+ // N.B. The callbacks must be registered outside of the above try/catch.
2872
+ // Otherwise if an exception is thrown, calling _VmTerminate() will trigger the 's_VmTerminated' termination callback
2873
+ // Which can deadlock since this thread holds the instance lock and HCS can block until the VM termination callback returns before deleting the VM.
2874
+
2875
+ m_utilityVm->RegisterCallbacks(std::bind(callback, _1), std::bind(s_VmTerminated, this, _1));
2876
}
2877
2878
_VmCheckIdle();