Fix #936: misuse of uninitialized objects causes AppVerifier breaks on Windows Terminal startup (#1015)
* move the render thread init up; gets rid of verifier stops * s/INVALID_HANDLE_VALUE/NULL/g since CreateEvent() and CreateThread() return a NULL HANDLE on failure; resolves another cause of AppVerifier breaks
This commit is contained in:
parent
5f938a0465
commit
9ad2544033
|
@ -297,13 +297,19 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||||
_terminal = std::make_unique<::Microsoft::Terminal::Core::Terminal>();
|
_terminal = std::make_unique<::Microsoft::Terminal::Core::Terminal>();
|
||||||
|
|
||||||
// First create the render thread.
|
// First create the render thread.
|
||||||
|
// Then stash a local pointer to the render thread so we can initialize it and enable it
|
||||||
|
// to paint itself *after* we hand off its ownership to the renderer.
|
||||||
|
// We split up construction and initialization of the render thread object this way
|
||||||
|
// because the renderer and render thread have circular references to each other.
|
||||||
auto renderThread = std::make_unique<::Microsoft::Console::Render::RenderThread>();
|
auto renderThread = std::make_unique<::Microsoft::Console::Render::RenderThread>();
|
||||||
// Stash a local pointer to the render thread, so we can enable it after
|
|
||||||
// we hand off ownership to the renderer.
|
|
||||||
auto* const localPointerToThread = renderThread.get();
|
auto* const localPointerToThread = renderThread.get();
|
||||||
|
|
||||||
|
// Now create the renderer and initialize the render thread.
|
||||||
_renderer = std::make_unique<::Microsoft::Console::Render::Renderer>(_terminal.get(), nullptr, 0, std::move(renderThread));
|
_renderer = std::make_unique<::Microsoft::Console::Render::Renderer>(_terminal.get(), nullptr, 0, std::move(renderThread));
|
||||||
::Microsoft::Console::Render::IRenderTarget& renderTarget = *_renderer;
|
::Microsoft::Console::Render::IRenderTarget& renderTarget = *_renderer;
|
||||||
|
|
||||||
|
THROW_IF_FAILED(localPointerToThread->Initialize(_renderer.get()));
|
||||||
|
|
||||||
// Set up the DX Engine
|
// Set up the DX Engine
|
||||||
auto dxEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>();
|
auto dxEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>();
|
||||||
_renderer->AddRenderEngine(dxEngine.get());
|
_renderer->AddRenderEngine(dxEngine.get());
|
||||||
|
@ -350,8 +356,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||||
auto inputFn = std::bind(&TermControl::_SendInputToConnection, this, std::placeholders::_1);
|
auto inputFn = std::bind(&TermControl::_SendInputToConnection, this, std::placeholders::_1);
|
||||||
_terminal->SetWriteInputCallback(inputFn);
|
_terminal->SetWriteInputCallback(inputFn);
|
||||||
|
|
||||||
THROW_IF_FAILED(localPointerToThread->Initialize(_renderer.get()));
|
|
||||||
|
|
||||||
auto chain = _renderEngine->GetSwapChain();
|
auto chain = _renderEngine->GetSwapChain();
|
||||||
_swapChainPanel.Dispatcher().RunAsync(CoreDispatcherPriority::High, [this, chain]()
|
_swapChainPanel.Dispatcher().RunAsync(CoreDispatcherPriority::High, [this, chain]()
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,42 +12,42 @@ using namespace Microsoft::Console::Render;
|
||||||
|
|
||||||
RenderThread::RenderThread() :
|
RenderThread::RenderThread() :
|
||||||
_pRenderer(nullptr),
|
_pRenderer(nullptr),
|
||||||
_hThread(INVALID_HANDLE_VALUE),
|
_hThread(nullptr),
|
||||||
_hEvent(INVALID_HANDLE_VALUE),
|
_hEvent(nullptr),
|
||||||
_hPaintCompletedEvent(INVALID_HANDLE_VALUE),
|
_hPaintCompletedEvent(nullptr),
|
||||||
_fKeepRunning(true),
|
_fKeepRunning(true),
|
||||||
_hPaintEnabledEvent(INVALID_HANDLE_VALUE)
|
_hPaintEnabledEvent(nullptr)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderThread::~RenderThread()
|
RenderThread::~RenderThread()
|
||||||
{
|
{
|
||||||
if (_hThread != INVALID_HANDLE_VALUE)
|
if (_hThread)
|
||||||
{
|
{
|
||||||
_fKeepRunning = false; // stop loop after final run
|
_fKeepRunning = false; // stop loop after final run
|
||||||
SignalObjectAndWait(_hEvent, _hThread, INFINITE, FALSE); // signal final paint and wait for thread to finish.
|
SignalObjectAndWait(_hEvent, _hThread, INFINITE, FALSE); // signal final paint and wait for thread to finish.
|
||||||
|
|
||||||
CloseHandle(_hThread);
|
CloseHandle(_hThread);
|
||||||
_hThread = INVALID_HANDLE_VALUE;
|
_hThread = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_hEvent != INVALID_HANDLE_VALUE)
|
if (_hEvent)
|
||||||
{
|
{
|
||||||
CloseHandle(_hEvent);
|
CloseHandle(_hEvent);
|
||||||
_hEvent = INVALID_HANDLE_VALUE;
|
_hEvent = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_hPaintEnabledEvent != INVALID_HANDLE_VALUE)
|
if (_hPaintEnabledEvent)
|
||||||
{
|
{
|
||||||
CloseHandle(_hPaintEnabledEvent);
|
CloseHandle(_hPaintEnabledEvent);
|
||||||
_hPaintEnabledEvent = INVALID_HANDLE_VALUE;
|
_hPaintEnabledEvent = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_hPaintCompletedEvent != INVALID_HANDLE_VALUE)
|
if (_hPaintCompletedEvent)
|
||||||
{
|
{
|
||||||
CloseHandle(_hPaintCompletedEvent);
|
CloseHandle(_hPaintCompletedEvent);
|
||||||
_hPaintCompletedEvent = INVALID_HANDLE_VALUE;
|
_hPaintCompletedEvent = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue