Skip to content

Commit 5d09719

Browse files
authored
Fix potential service deadlock when plugin returns an error from OnVmStarted (#13569)
1 parent 8540b2b commit 5d09719

1 file changed

Lines changed: 28 additions & 24 deletions

File tree

src/windows/service/exe/LxssUserSession.cpp

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2814,30 +2814,6 @@ void LxssUserSessionImpl::_CreateVm()
28142814

28152815
try
28162816
{
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-
28412817
// Mount disks after the system distro vhd is mounted in case filesystem detection is needed.
28422818
_LoadDiskMounts();
28432819

@@ -2869,6 +2845,34 @@ void LxssUserSessionImpl::_CreateVm()
28692845
_VmTerminate();
28702846
throw;
28712847
}
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));
28722876
}
28732877

28742878
_VmCheckIdle();

0 commit comments

Comments
 (0)