Skip to content

Commit

Permalink
Fix a race condition in CTerminalHandoff::s_StopListening (#13410)
Browse files Browse the repository at this point in the history
This commit fixes a minor race condition covered as part of #13368.
The member `_pfnHandoff` was read without the mutex `_mtx` being locked first.
The issue was solved by acquiring the lock early and running the entire
`s_StopListening` function with that lock held.

(cherry picked from commit 95a1962)
Service-Card-Id: 83893125
Service-Version: 1.14
  • Loading branch information
lhecker authored and DHowett committed Jul 5, 2022
1 parent e5239f8 commit d7d15db
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 4 deletions.
15 changes: 11 additions & 4 deletions src/cascadia/TerminalConnection/CTerminalHandoff.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,12 @@ CATCH_RETURN()
HRESULT CTerminalHandoff::s_StopListening()
{
std::unique_lock lock{ _mtx };
return s_StopListeningLocked();
}

// See s_StopListening()
HRESULT CTerminalHandoff::s_StopListeningLocked()
{
RETURN_HR_IF_NULL(E_NOT_VALID_STATE, _pfnHandoff);

_pfnHandoff = nullptr;
Expand Down Expand Up @@ -101,14 +106,16 @@ HRESULT CTerminalHandoff::EstablishPtyHandoff(HANDLE in, HANDLE out, HANDLE sign
{
try
{
// Stash a local copy of _pfnHandoff before we stop listening.
std::unique_lock lock{ _mtx };

// s_StopListeningLocked sets _pfnHandoff to nullptr.
// localPfnHandoff is tested for nullness below.
#pragma warning(suppress : 26429) // Symbol '...' is never tested for nullness, it can be marked as not_null (f.23).
auto localPfnHandoff = _pfnHandoff;

// Because we are REGCLS_SINGLEUSE... we need to `CoRevokeClassObject` after we handle this ONE call.
// COM does not automatically clean that up for us. We must do it.
s_StopListening();

std::unique_lock lock{ _mtx };
LOG_IF_FAILED(s_StopListeningLocked());

// Report an error if no one registered a handoff function before calling this.
THROW_HR_IF_NULL(E_NOT_VALID_STATE, localPfnHandoff);
Expand Down
3 changes: 3 additions & 0 deletions src/cascadia/TerminalConnection/CTerminalHandoff.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ struct __declspec(uuid(__CLSID_CTerminalHandoff))

static HRESULT s_StartListening(NewHandoffFunction pfnHandoff);
static HRESULT s_StopListening();

private:
static HRESULT s_StopListeningLocked();
};

// Disable warnings from the CoCreatableClass macro as the value it provides for
Expand Down

0 comments on commit d7d15db

Please sign in to comment.