terminal/src/host/ScreenBufferRenderTarget.hpp
Leonard Hecker ac265aab99
Fix TerminalControl crash on exit (#10031)
## Summary of the Pull Request

ControlCore's _renderer (IRenderTarget) is allocated as std::unique_ptr,
but is given to Terminal::CreateFromSettings as a reference.
ControlCore::Close deallocates the _renderer, but if ThrottledFuncs
are still scheduled to call ControlCore::UpdatePatternLocations
it'll cause Terminal::UpdatePatterns to be called, which in turn ends up
accessing the deallocated IRenderTarget reference and lead to a crash.

A proper solution with shared pointers is nontrivial and should be
attempted at a later point in time. This solution moves the teardown of
the _renderer into ControlCore::~ControlCore, where we can be certain
that no further strong references are held by ThrottledFuncs.

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

## Validation Steps Performed

The crash is a race condition and inherently hard to reproduce.
During validation this PR didn't appear to introduce new crashes.
2021-05-04 21:17:37 +00:00

46 lines
1.4 KiB
C++

/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- ScreenBufferRenderTarget.hpp
Abstract:
Provides an encapsulation for all of the RenderTarget methods for the SCreenBuffer.
Unfortunately, these cannot be defined directly on the SCREEN_INFORMATION due to
MSFT 9358743.
Adding an interface to SCREEN_INFORMATION makes the ConsoleObjectHeader no
longer the first part of the SCREEN_INFORMATION.
The Screen buffer will pass this object to other objects that need to trigger
redrawing the buffer contents.
Author(s):
- Mike Griese (migrie) Nov 2018
--*/
#pragma once
#include "../renderer/inc/IRenderTarget.hpp"
// fwdecl
class SCREEN_INFORMATION;
class ScreenBufferRenderTarget final : public Microsoft::Console::Render::IRenderTarget
{
public:
ScreenBufferRenderTarget(SCREEN_INFORMATION& owner);
void TriggerRedraw(const Microsoft::Console::Types::Viewport& region) override;
void TriggerRedraw(const COORD* const pcoord) override;
void TriggerRedrawCursor(const COORD* const pcoord) override;
void TriggerRedrawAll() override;
void TriggerTeardown() noexcept override;
void TriggerSelection() override;
void TriggerScroll() override;
void TriggerScroll(const COORD* const pcoordDelta) override;
void TriggerCircling() override;
void TriggerTitleChange() override;
private:
SCREEN_INFORMATION& _owner;
};