Fix unbalanced unlock in PtySignalInputThread::_Shutdown (#12181)

The only way to notice that LeaveCriticalSection() was called more
often than EnterCriticalSection() is by calling EnterCriticalSection()
again in the future, which will then deadlock.
Since this bug occurs on exit it wasn't noticeable with the old console lock.
With the new, stricter ticket lock this bug causes a fail-fast exit.

## PR Checklist
* [x] Closes #12168
* [x] I work here
* [x] Tests added/passed

## Validation Steps Performed
* Launch and then exit Windows Terminal
* OpenConsole cleanly exits 
This commit is contained in:
Leonard Hecker
2022-01-25 00:36:06 +01:00
committed by GitHub
parent 43a275c754
commit 3bd3a4f712
6 changed files with 7 additions and 8 deletions

View File

@@ -170,7 +170,6 @@ bool PtySignalInputThread::_GetData(_Out_writes_bytes_(cbBuffer) void* const pBu
if (lastError == ERROR_BROKEN_PIPE)
{
_Shutdown();
return false;
}
else
{
@@ -180,7 +179,6 @@ bool PtySignalInputThread::_GetData(_Out_writes_bytes_(cbBuffer) void* const pBu
else if (dwRead != cbBuffer)
{
_Shutdown();
return false;
}
return true;
@@ -233,6 +231,7 @@ void PtySignalInputThread::_Shutdown()
// happens if this method is called outside of lock, but if we're
// currently locked, we want to make sure ctrl events are handled
// _before_ we RundownAndExit.
LockConsole();
ProcessCtrlEvents();
// Make sure we terminate.

View File

@@ -10,6 +10,7 @@
#include "../renderer/base/renderer.hpp"
#include "../types/inc/utils.hpp"
#include "handle.h" // LockConsole
#include "input.h" // ProcessCtrlEvents
#include "output.h" // CloseConsoleProcessState
@@ -383,6 +384,7 @@ void VtIo::_ShutdownIfNeeded()
// happens if this method is called outside of lock, but if we're
// currently locked, we want to make sure ctrl events are handled
// _before_ we RundownAndExit.
LockConsole();
ProcessCtrlEvents();
// Make sure we terminate.

View File

@@ -520,5 +520,5 @@ void CloseConsoleProcessState()
// ctrl event will never actually get dispatched.
// So, lock and unlock here, to make sure the ctrl event gets handled.
LockConsole();
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
UnlockConsole();
}

View File

@@ -163,7 +163,6 @@ bool HostSignalInputThread::_GetData(gsl::span<gsl::byte> buffer)
if (lastError == ERROR_BROKEN_PIPE)
{
_Shutdown();
return false;
}
THROW_WIN32(lastError);
@@ -172,7 +171,6 @@ bool HostSignalInputThread::_GetData(gsl::span<gsl::byte> buffer)
if (bytesRead != buffer.size())
{
_Shutdown();
return false;
}
return true;

View File

@@ -34,7 +34,7 @@ wil::unique_hwnd ServiceLocator::s_pseudoWindow = nullptr;
#pragma region Public Methods
void ServiceLocator::RundownAndExit(const HRESULT hr)
[[noreturn]] void ServiceLocator::RundownAndExit(const HRESULT hr)
{
// MSFT:15506250
// In VT I/O Mode, a client application might die before we've rendered
@@ -67,7 +67,7 @@ void ServiceLocator::RundownAndExit(const HRESULT hr)
s_inputServices.reset(nullptr);
}
TerminateProcess(GetCurrentProcess(), hr);
ExitProcess(hr);
}
#pragma region Creation Methods

View File

@@ -30,7 +30,7 @@ namespace Microsoft::Console::Interactivity
class ServiceLocator final
{
public:
static void RundownAndExit(const HRESULT hr);
[[noreturn]] static void RundownAndExit(const HRESULT hr);
// N.B.: Location methods without corresponding creation methods
// automatically create the singleton object on demand.