Skip to content

Conversation

@OneBlue
Copy link
Collaborator

@OneBlue OneBlue commented Sep 18, 2025

Summary of the Pull Request

This change adds new logic to force terminate the VM if we can't acquire the user session lock for 30 seconds. This should help avoid MSI installation being stuck because wslservice is waiting on the lock to terminate the VM (See #11013).

Thiswill only help when upgrading into a build that contains this commit, so we should expect the new upgrade to show the same issues.

PR Checklist

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

Detailed Description of the Pull Request / Additional comments

Validation Steps Performed

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds timeout logic to force terminate the WSL VM when the session lock cannot be acquired within 30 seconds during service shutdown, addressing installation hangs caused by deadlocks on the session lock.

  • Adds a new ShutdownBehavior enum with timeout options for VM shutdown
  • Changes the session mutex from std::recursive_mutex to std::recursive_timed_mutex to support timeout operations
  • Implements timeout logic that force terminates the VM after 30 seconds if the lock can't be acquired

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
LxssUserSession.h Adds ShutdownBehavior enum and changes mutex type to support timeouts
LxssUserSession.cpp Implements timeout logic and refactors shutdown method to use new behavior enum
LxssUserSessionFactory.cpp Updates shutdown call to use new ForceAfter30Seconds behavior

Comment on lines +2082 to +2087
auto unlock = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [this, &locked]() {
if (locked)
{
m_instanceLock.unlock();
}
});
Copy link

Copilot AI Sep 18, 2025

Choose a reason for hiding this comment

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

The scope_exit handler captures locked by reference, but locked will go out of scope when the function returns. This could lead to undefined behavior if the scope_exit handler is invoked after the function returns. Consider capturing locked by value or using a different synchronization approach.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is incorrect. Capturing locked by value would break the logic of this scope_exit

Comment on lines +2081 to +2107
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;
}

Copy link

Copilot AI Sep 18, 2025

Choose a reason for hiding this comment

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

If Behavior != ShutdownBehavior::ForceAfter30Seconds, the locked variable remains false and this block will always execute a blocking lock. This logic could be simplified by handling the different shutdown behaviors more explicitly to improve code clarity.

Suggested change
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;
}
auto unlock = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [this]() {
m_instanceLock.unlock();
});
switch (Behavior)
{
case ShutdownBehavior::ForceAfter30Seconds:
if (!m_instanceLock.try_lock_for(std::chrono::seconds(30)))
{
WSL_LOG("VmShutdownLockTimedOut");
forceTerminate();
// Lock not acquired, so skip further shutdown steps.
return;
}
break;
default:
m_instanceLock.lock();
break;
}

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, that's the point. We should not access member variables without the lock

Copy link
Member

@benhillis benhillis left a comment

Choose a reason for hiding this comment

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

:shipit:

@OneBlue OneBlue merged commit 4bba074 into master Sep 24, 2025
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants