Skip to content

Ensure the C++ UIA rate limited event handler flusher thread is definitely terminated when NVDA shutts down#16198

Merged
seanbudd merged 3 commits intobetafrom
i16072
Feb 22, 2024
Merged

Ensure the C++ UIA rate limited event handler flusher thread is definitely terminated when NVDA shutts down#16198
seanbudd merged 3 commits intobetafrom
i16072

Conversation

@michaelDCurran
Copy link
Member

Link to issue number:

Fixes #16072

Summary of the issue:

If any background threads remain after NVDA exits, the NVDA process will stay alive until those background threads complete. For Python threads, setting daemon to true on the thread causes Python to kill off the thread when the main thread exits. However, Python is unaware of C++ threads.
One particular C++ thread which has proven to keep NvDA alive for at least one person (see #16072) is the UIA rate limited event handler flusher thread.
We should try much harder to ensure that this thread is terminated during NVDA exit so that it does not keep the NVDA process alive after the main thread exits.

Description of user facing changes

The NVDA process is less likely to stay around after NvDA has exited, which means that NVDA should no longer freeze on restart and NvDA updates should be less likely to fail due to NVDA still running.

Description of development approach

  • UIA rate limited event handler: improve logic and logging of the flusher thread function to make it clearer as to why the thread will wake for flushes or when it should stop.
  • Add the ability to terminate UIA rate limited event handler's flusher thread upon request via a new terminate API call. This allows NvDA to ensure that the flusher thread can be terminated, even if it may not release the rate limited event handler COM object reference for some reason.
  • UIAHandler.terminate: specifically terminate the rate limited event handler from NvDA's main thread, before trying to terminate the UIA MTA thread. This ensures that the c++ UIA rate limitied event handler flusher thread is definitely terminated, even if there may be further errors terminating the UIA MTA Python thread.

Testing strategy:

  • Compiled NVDAHelperLocal with debug logging enabled.
  • Ensured that NVDA's Enhanced UIA event processing advanced option is turned on.
  • Started and quit NvDA several times.
  • Confirmed in NvDA's log that the UIA rate limited event hander flusher thread correctly woke and terminated durng UIAHandler.terminate.
  • The reporter of Portable version of NVDA starts very slowly and is unusable #16072 would still need to test and confirm that this change stops the issues they are experiencing.

Known issues with pull request:

None known.

Code Review Checklist:

  • Documentation:
    • Change log entry
    • User Documentation
    • Developer / Technical Documentation
    • Context sensitive help for GUI changes
  • Testing:
    • Unit tests
    • System (end to end) tests
    • Manual testing
  • UX of all users considered:
    • Speech
    • Braille
    • Low Vision
    • Different web browsers
    • Localization in other languages / culture than English
  • API is compatible with existing add-ons.
  • Security precautions taken.

…her thread function to make it clearer as to why the thread will wake for flushes or when it should stop.

* Add the ability to terminate UIA rate limited event handler's flusher thread upon request via a new terminate API call. this allows NvDA to ensure that the flusher thread can be terminated, even if it may not release the rate limited event handler COM object reference for some reason.
* UIAHandler.terminate: specifically terminate the rate limited event handler from NvDA's main thread, before trying to terminate the UIA MTA thread. This ensures that the c++ UIA rate limitied event handler flusher thread is definitely terminated, even if there may be further errors terminating the UIA MTA Python thread.
@michaelDCurran michaelDCurran requested a review from a team as a code owner February 20, 2024 12:49
@michaelDCurran michaelDCurran requested review from seanbudd and removed request for a team February 20, 2024 12:49
@lukaszgo1
Copy link
Contributor

I assume it is not clear why the thread fails to end normally for the reporter of #16072 ? Would it be possible to debug this further, perhaps with additional logging? Obviously for 2024.1 it is important the thread gets terminated and does not block NVDA's main process, but perhaps for next release understanding the real cause may prove useful.

@michaelDCurran
Copy link
Member Author

michaelDCurran commented Feb 20, 2024 via email

Co-authored-by: Łukasz Golonka <lukasz.golonka@mailbox.org>
@seanbudd seanbudd added this to the 2024.1 milestone Feb 21, 2024
seanbudd
seanbudd previously approved these changes Feb 21, 2024
Copy link
Member

@seanbudd seanbudd left a comment

Choose a reason for hiding this comment

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

just minor lint fixes

Copy link
Member

@seanbudd seanbudd left a comment

Choose a reason for hiding this comment

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

just minor lint fixes

@AppVeyorBot
Copy link

See test results for failed build of commit 189363a4d1

@seanbudd seanbudd merged commit a1e19cd into beta Feb 22, 2024
@seanbudd seanbudd deleted the i16072 branch February 22, 2024 01:06
Adriani90 pushed a commit to Adriani90/nvda that referenced this pull request Mar 13, 2024
…itely terminated when NVDA shutts down (nvaccess#16198)

Fixes nvaccess#16072

Summary of the issue:
If any background threads remain after NVDA exits, the NVDA process will stay alive until those background threads complete. For Python threads, setting daemon to true on the thread causes Python to kill off the thread when the main thread exits. However, Python is unaware of C++ threads.
One particular C++ thread which has proven to keep NvDA alive for at least one person (see nvaccess#16072) is the UIA rate limited event handler flusher thread.
We should try much harder to ensure that this thread is terminated during NVDA exit so that it does not keep the NVDA process alive after the main thread exits.

Description of user facing changes
The NVDA process is less likely to stay around after NvDA has exited, which means that NVDA should no longer freeze on restart and NvDA updates should be less likely to fail due to NVDA still running.

Description of development approach
UIA rate limited event handler: improve logic and logging of the flusher thread function to make it clearer as to why the thread will wake for flushes or when it should stop.
Add the ability to terminate UIA rate limited event handler's flusher thread upon request via a new terminate API call. This allows NvDA to ensure that the flusher thread can be terminated, even if it may not release the rate limited event handler COM object reference for some reason.
UIAHandler.terminate: specifically terminate the rate limited event handler from NvDA's main thread, before trying to terminate the UIA MTA thread. This ensures that the c++ UIA rate limitied event handler flusher thread is definitely terminated, even if there may be further errors terminating the UIA MTA Python thread.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants