Skip to content

[a11y] Ensure buffer is initialized before interacting with it - #11312

Merged
Carlos Zamora (carlos-zamora) merged 3 commits into
mainfrom
dev/cazamor/a11y-initialize-hang
Sep 23, 2021
Merged

Carlos Zamora (carlos-zamora) merged 3 commits into
mainfrom
dev/cazamor/a11y-initialize-hang

Conversation

@carlos-zamora

@carlos-zamora Carlos Zamora (carlos-zamora) commented Sep 23, 2021 •

Copy link
Copy Markdown

Summary of the Pull Request

Adds a check before every UIA function call to ensure the terminal (specifically the buffer) is initialized before doing work. Both the ScreenInfoUiaProvider and the UiaTextRange are now covered.

References

Closes #11135
#10971 & #11042

Detailed Description of the Pull Request / Additional comments

Originally, I tried applying this heuristic to all the RuntimeClassInitialize on UiaTextRangeBase with the philosophy of "a range pointing to an invalid buffer is invalid itself", but that caused a regression on MSFT 33353327.

IUiaData also has GetTextBuffer() return a TextBuffer&, which cannot be checked for nullness. Instead, I decided to add a function to IUiaData that checks if we have a valid state. Since this is shared with Conhost and Conhost doesn't have this issue, I simply make that function say that it's always in a valid state.

Validation Steps Performed

  • Narrator can detect newly created terminals
  • (On Windows Server 2022) Windows Terminal does not hang on launch

@ghost ghost added Area-TerminalControl Issues pertaining to the terminal control (input, selection, keybindings, mouse interaction, etc.) Issue-Bug It either shouldn't be doing this or needs an investigation. Priority-0 Bugs that we consider release-blocking/recall-class (P0) Product-Terminal The new Windows Terminal. Severity-Blocking We won't ship a release like this! No-siree. labels Sep 23, 2021
@carlos-zamora

Copy link
Copy Markdown
Author

Michael Niksa (@miniksa) made an update to the branch (added comments and initialization checks in ScreenInfoUiaProviderBase). You said ScreenInfoUiaProviderBase::GetSelection was the culprit, so you'll need to test this build on the VM.

Once we verify that this works on Windows Server, this'll be out of draft.

@carlos-zamora
Carlos Zamora (carlos-zamora) marked this pull request as ready for review September 23, 2021 16:49
@miniksa

Copy link
Copy Markdown
Contributor

I've done a manual test on https://microsoft.visualstudio.com/c93e867a-8815-43c1-92c4-e7dd5404f1e1/_build/results?buildId=39411475 on the Windows Server 2022 machine by launching the Terminal built with these changes using the tablet input keyboard and it loads up normally.

@carlos-zamora

Copy link
Copy Markdown
Author

Michael Niksa (@miniksa) we should be able to just cherry-pick this into 1.10 too

Comment thread src/types/ScreenInfoUiaProviderBase.cpp Outdated
Comment on lines +280 to +284
if (!_pData->IsUiaDataInitialized())
{
return E_FAIL;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Isn't this on the wrong side of the lock? Or alternatively, shouldn't the value be atomic or something?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Eh I guess if it comes back as a dirty "false" it only goes to "true" once and a missed early call is OK. So maybe nevermind.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Leonard Hecker (@lhecker) can you comment on this before we merge? Do you think this is OK as is?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Theoretically it's not okay. Practically it'll work on any modern CPU.
The reason it's not save theoretically is because the standard says:

If a data race occurs, the behavior of the program is undefined.

So theoretically speaking, the moment you have a race condition your computer could turn into a mahou shoujo.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

So what's better to you? Moving it all past the existing call to the til::ticket_lock or using an std::atomic<bool> on this flag?

@zadjii-msft Mike Griese (zadjii-msft) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Honestly, I'm fine shipping this as-is, but the WIL macros are nice

Comment thread src/types/ScreenInfoUiaProviderBase.cpp Resolved
Comment thread src/types/ScreenInfoUiaProviderBase.cpp Resolved
@carlos-zamora

Copy link
Copy Markdown
Author

https://microsoft.visualstudio.com/c93e867a-8815-43c1-92c4-e7dd5404f1e1/_build/results?buildId=39422176 works on the Windows Server 2022 machine by launching the Terminal built with these changes using the tablet input keyboard and it loads up normally. (Verified)

@carlos-zamora
Carlos Zamora (carlos-zamora) deleted the dev/cazamor/a11y-initialize-hang branch September 23, 2021 22:14
Carlos Zamora (carlos-zamora) pushed a commit that referenced this pull request Sep 23, 2021
Adds a check before every UIA function call to ensure the terminal (specifically the buffer) is initialized before doing work. Both the `ScreenInfoUiaProvider` and the `UiaTextRange` are now covered.

## References
Closes #11135 
#10971 & #11042

## Detailed Description of the Pull Request / Additional comments
Originally, I tried applying this heuristic to all the `RuntimeClassInitialize` on `UiaTextRangeBase` with the philosophy of "a range pointing to an invalid buffer is invalid itself", but that caused a regression on [MSFT 33353327](https://microsoft.visualstudio.com/OS/_workitems/edit/33353327).

`IUiaData` also has `GetTextBuffer()` return a `TextBuffer&`, which cannot be checked for nullness. Instead, I decided to add a function to `IUiaData` that checks if we have a valid state. Since this is shared with Conhost and Conhost doesn't have this issue, I simply make that function say that it's always in a valid state.

## Validation Steps Performed
- [X] Narrator can detect newly created terminals
- [X] (On Windows Server 2022) Windows Terminal does not hang on launch
Carlos Zamora (carlos-zamora) pushed a commit that referenced this pull request Sep 23, 2021
Adds a check before every UIA function call to ensure the terminal (specifically the buffer) is initialized before doing work. Both the `ScreenInfoUiaProvider` and the `UiaTextRange` are now covered.

## References
Closes #11135 
#10971 & #11042

## Detailed Description of the Pull Request / Additional comments
Originally, I tried applying this heuristic to all the `RuntimeClassInitialize` on `UiaTextRangeBase` with the philosophy of "a range pointing to an invalid buffer is invalid itself", but that caused a regression on [MSFT 33353327](https://microsoft.visualstudio.com/OS/_workitems/edit/33353327).

`IUiaData` also has `GetTextBuffer()` return a `TextBuffer&`, which cannot be checked for nullness. Instead, I decided to add a function to `IUiaData` that checks if we have a valid state. Since this is shared with Conhost and Conhost doesn't have this issue, I simply make that function say that it's always in a valid state.

## Validation Steps Performed
- [X] Narrator can detect newly created terminals
- [X] (On Windows Server 2022) Windows Terminal does not hang on launch
ghost pushed a commit that referenced this pull request Sep 30, 2021
## Summary of the Pull Request
The deadlock was caused by `ScreenInfoUiaProviderBase::GetSelection()` calling `TermControlUiaProvider::GetSelectionRange` (both of which attempted to lock the console). This PR removes the lock and initialization check from `TermControlUiaProvider`. It is no longer necessary because the only one that calls it is `SIUPB::GetSelection()`.

Additionally, this adds some code that was useful in debugging this race condition. That should help us figure out any locking issues that may come up in the future.

## References
#11312
Closes #11385 

## Validation Steps Performed
✅ Repro steps don't cause hang
Carlos Zamora (carlos-zamora) pushed a commit that referenced this pull request Sep 30, 2021
## Summary of the Pull Request
The deadlock was caused by `ScreenInfoUiaProviderBase::GetSelection()` calling `TermControlUiaProvider::GetSelectionRange` (both of which attempted to lock the console). This PR removes the lock and initialization check from `TermControlUiaProvider`. It is no longer necessary because the only one that calls it is `SIUPB::GetSelection()`.

Additionally, this adds some code that was useful in debugging this race condition. That should help us figure out any locking issues that may come up in the future.

## References
#11312
Closes #11385 

## Validation Steps Performed
✅ Repro steps don't cause hang
@ghost

Copy link
Copy Markdown

🎉Windows Terminal v1.10.2714.0 has been released which incorporates this pull request.:tada:

Handy links:

@ghost

Copy link
Copy Markdown

🎉Windows Terminal Preview v1.11.2731.0 has been released which incorporates this pull request.:tada:

Handy links:

@ghost

Copy link
Copy Markdown

🎉Windows Terminal Preview v1.12.2922.0 has been released which incorporates this pull request.:tada:

Handy links:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area-TerminalControl Issues pertaining to the terminal control (input, selection, keybindings, mouse interaction, etc.) Issue-Bug It either shouldn't be doing this or needs an investigation. Priority-0 Bugs that we consider release-blocking/recall-class (P0) Product-Terminal The new Windows Terminal. Severity-Blocking We won't ship a release like this! No-siree.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Terminal hangs when opening new windows or new tabs on Windows Server 2022

4 participants