Skip to content

Properly destroy Add-on Store dialog when it is closed#16019

Merged
seanbudd merged 2 commits into
nvaccess:betafrom
lukaszgo1:storeDialogNoCircularRef
Jan 9, 2024
Merged

Properly destroy Add-on Store dialog when it is closed#16019
seanbudd merged 2 commits into
nvaccess:betafrom
lukaszgo1:storeDialogNoCircularRef

Conversation

@lukaszgo1

@lukaszgo1 lukaszgo1 commented Jan 9, 2024

Copy link
Copy Markdown
Contributor

Opened against beta, since even though the issue was not introduced in 2024.1 development cycle, its effect can be quite serious. Additionally this change is small and very low risk.

Link to issue number:

Related to #15041 and #15105

Summary of the issue:

Ever since Add-on Store was introduced NVDA was intermittently failing to restart on my machine. This occurred only when I've opened Add-on Store before restarting. After debugging it turned out the following happens:

  • When exiting NVDA had to destroy the store dialog, as it was kept alive due to circular reference
  • The new instance of NVDA tried to wait for the old instance to exit, but since the exit process took extra long due to destroying the dialog the new copy gave up and didn't start

Description of user facing changes

NVDA should no longer fail to restart intermittently after opening and closing Add-on Store.

Description of development approach

The reference to one of BoxSizerHelper objects was stored on the store dialog. Since each BoxSizerHelper also stores reference to its parent the store dialog could not be destroyed properly when closing. This circular reference cycle was broken by no longer storing the BoxSizerHelper on the instance - it is either used as a local variable, or passed to the method which needs it as an parameter.

Testing strategy:

  • Ensured store dialog is still functioning
  • Stress tested restarting NVDA on a machine where this was failing and verified it restarts successfully every single time
  • Ensured no instances are stored in gui.settingsDialogs.SettingsDialog._instances when the Add-on Store dialog is closed

Known issues with pull request:

  • Storing a BoxSizerHelper as a dialog member is an easy mistake to make in the future. I will submit a PR which makes it less likely to occur by storing a weak reference to the parent in the helper instance. Since this is a bigger and more risky change it will target master
  • The approach taken by Add-on Store: prevent duplicate instances from opening #15105 i.e. ignoring the warning about existing instances is sub-optimal. As demonstrated by this PR ignoring these alive references may cause issues in unrelated areas of NVDA. In my opinion we should restore the old behavior i.e. live references should once again cause a warning. If this is fine I'll submit a PR to that effect against master.

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.

@lukaszgo1 lukaszgo1 force-pushed the storeDialogNoCircularRef branch from 7b6795d to b3cc188 Compare January 9, 2024 20:14
@lukaszgo1 lukaszgo1 changed the base branch from master to beta January 9, 2024 20:16
@lukaszgo1 lukaszgo1 marked this pull request as ready for review January 9, 2024 20:44
@lukaszgo1 lukaszgo1 requested a review from a team as a code owner January 9, 2024 20:44
@lukaszgo1 lukaszgo1 requested review from seanbudd and removed request for a team January 9, 2024 20:44
@seanbudd seanbudd added this to the 2024.1 milestone Jan 9, 2024
@seanbudd

seanbudd commented Jan 9, 2024

Copy link
Copy Markdown
Member

Thanks @lukaszgo1 for hunting this down - please go ahead with both PRs to master when you can

@seanbudd seanbudd merged commit 97886b0 into nvaccess:beta Jan 9, 2024
@lukaszgo1 lukaszgo1 deleted the storeDialogNoCircularRef branch January 10, 2024 10:41
seanbudd pushed a commit that referenced this pull request Jan 22, 2024
…hey are closed (#16054)

Follow up from PR #16019

Summary of the issue:
Normally it should not be possible to open the same NVDA's settings dialog multiple times. To make sure this does not happen settings dialog constructor verifies if the given dialog is already opened, and either focuses it when it is, or creates a new dialog when it is not. In rare cases the dialog should be destroyed after user closed it, but due to circular reference Python's garbage collector cannot clean it up. Before PR #15105 this was causing an error making it impossible to reopen the dialog. In that PR the behavior was changed, so that when the instance is still kept alive it is just marked as created and reused. As described in PR #16019 when dialogs are not destroyed properly NVDA may malfunction, so having an error and non working dialog is better than a hard to debug error in other part of NVDA.

Description of user facing changes
This should not have user visible impact, as long as there are no dialogs which fail to be destroyed when they are closed.

Description of development approach
When there is an existing instance of a given dialog which is marked as destroyed there is an error in the log, and no other instances of this dialog can be created.
seanbudd pushed a commit that referenced this pull request Jan 23, 2024
…zerHelper to decrease likelihood of circular references in NVDA's GUI (#16079)

Related to #16019

Summary of the issue:
BoxSizerHelper class stores a strong reference to its parent. When it is mistakenly assigned to a member of its parent a circular reference is created making it impossible for Python's garbage collector to destroy the dialog when it goes out of scope.

Description of user facing changes
Should not be noticeable.

Description of development approach
BoxSizerHelper now stores a weak reference to its parent.
Nael-Sayegh pushed a commit to Nael-Sayegh/nvda that referenced this pull request Feb 15, 2024
…hey are closed (nvaccess#16054)

Follow up from PR nvaccess#16019

Summary of the issue:
Normally it should not be possible to open the same NVDA's settings dialog multiple times. To make sure this does not happen settings dialog constructor verifies if the given dialog is already opened, and either focuses it when it is, or creates a new dialog when it is not. In rare cases the dialog should be destroyed after user closed it, but due to circular reference Python's garbage collector cannot clean it up. Before PR nvaccess#15105 this was causing an error making it impossible to reopen the dialog. In that PR the behavior was changed, so that when the instance is still kept alive it is just marked as created and reused. As described in PR nvaccess#16019 when dialogs are not destroyed properly NVDA may malfunction, so having an error and non working dialog is better than a hard to debug error in other part of NVDA.

Description of user facing changes
This should not have user visible impact, as long as there are no dialogs which fail to be destroyed when they are closed.

Description of development approach
When there is an existing instance of a given dialog which is marked as destroyed there is an error in the log, and no other instances of this dialog can be created.
Nael-Sayegh pushed a commit to Nael-Sayegh/nvda that referenced this pull request Feb 15, 2024
…zerHelper to decrease likelihood of circular references in NVDA's GUI (nvaccess#16079)

Related to nvaccess#16019

Summary of the issue:
BoxSizerHelper class stores a strong reference to its parent. When it is mistakenly assigned to a member of its parent a circular reference is created making it impossible for Python's garbage collector to destroy the dialog when it goes out of scope.

Description of user facing changes
Should not be noticeable.

Description of development approach
BoxSizerHelper now stores a weak reference to its parent.
SaschaCowley pushed a commit to SaschaCowley/nvda that referenced this pull request Feb 27, 2024
…hey are closed (nvaccess#16054)

Follow up from PR nvaccess#16019

Summary of the issue:
Normally it should not be possible to open the same NVDA's settings dialog multiple times. To make sure this does not happen settings dialog constructor verifies if the given dialog is already opened, and either focuses it when it is, or creates a new dialog when it is not. In rare cases the dialog should be destroyed after user closed it, but due to circular reference Python's garbage collector cannot clean it up. Before PR nvaccess#15105 this was causing an error making it impossible to reopen the dialog. In that PR the behavior was changed, so that when the instance is still kept alive it is just marked as created and reused. As described in PR nvaccess#16019 when dialogs are not destroyed properly NVDA may malfunction, so having an error and non working dialog is better than a hard to debug error in other part of NVDA.

Description of user facing changes
This should not have user visible impact, as long as there are no dialogs which fail to be destroyed when they are closed.

Description of development approach
When there is an existing instance of a given dialog which is marked as destroyed there is an error in the log, and no other instances of this dialog can be created.
SaschaCowley pushed a commit to SaschaCowley/nvda that referenced this pull request Feb 27, 2024
…zerHelper to decrease likelihood of circular references in NVDA's GUI (nvaccess#16079)

Related to nvaccess#16019

Summary of the issue:
BoxSizerHelper class stores a strong reference to its parent. When it is mistakenly assigned to a member of its parent a circular reference is created making it impossible for Python's garbage collector to destroy the dialog when it goes out of scope.

Description of user facing changes
Should not be noticeable.

Description of development approach
BoxSizerHelper now stores a weak reference to its parent.
Adriani90 pushed a commit to Adriani90/nvda that referenced this pull request Mar 13, 2024
Related to nvaccess#15041 and nvaccess#15105

Summary of the issue:
Ever since Add-on Store was introduced NVDA was intermittently failing to restart on my machine. This occurred only when I've opened Add-on Store before restarting. After debugging it turned out the following happens:

When exiting NVDA had to destroy the store dialog, as it was kept alive due to circular reference
The new instance of NVDA tried to wait for the old instance to exit, but since the exit process took extra long due to destroying the dialog the new copy gave up and didn't start
Description of user facing changes
NVDA should no longer fail to restart intermittently after opening and closing Add-on Store.

Description of development approach
The reference to one of BoxSizerHelper objects was stored on the store dialog. Since each BoxSizerHelper also stores reference to its parent the store dialog could not be destroyed properly when closing. This circular reference cycle was broken by no longer storing the BoxSizerHelper on the instance - it is either used as a local variable, or passed to the method which needs it as an parameter.

Testing strategy:
Ensured store dialog is still functioning
Stress tested restarting NVDA on a machine where this was failing and verified it restarts successfully every single time
Ensured no instances are stored in gui.settingsDialogs.SettingsDialog._instances when the Add-on Store dialog is closed
Known issues with pull request:
Storing a BoxSizerHelper as a dialog member is an easy mistake to make in the future. I will submit a PR which makes it less likely to occur by storing a weak reference to the parent in the helper instance. Since this is a bigger and more risky change it will target master
The approach taken by Add-on Store: prevent duplicate instances from opening nvaccess#15105 i.e. ignoring the warning about existing instances is sub-optimal. As demonstrated by this PR ignoring these alive references may cause issues in unrelated areas of NVDA. In my opinion we should restore the old behavior i.e. live references should once again cause a warning. If this is fine I'll submit a PR to that effect against master.
Adriani90 pushed a commit to Adriani90/nvda that referenced this pull request Mar 13, 2024
…hey are closed (nvaccess#16054)

Follow up from PR nvaccess#16019

Summary of the issue:
Normally it should not be possible to open the same NVDA's settings dialog multiple times. To make sure this does not happen settings dialog constructor verifies if the given dialog is already opened, and either focuses it when it is, or creates a new dialog when it is not. In rare cases the dialog should be destroyed after user closed it, but due to circular reference Python's garbage collector cannot clean it up. Before PR nvaccess#15105 this was causing an error making it impossible to reopen the dialog. In that PR the behavior was changed, so that when the instance is still kept alive it is just marked as created and reused. As described in PR nvaccess#16019 when dialogs are not destroyed properly NVDA may malfunction, so having an error and non working dialog is better than a hard to debug error in other part of NVDA.

Description of user facing changes
This should not have user visible impact, as long as there are no dialogs which fail to be destroyed when they are closed.

Description of development approach
When there is an existing instance of a given dialog which is marked as destroyed there is an error in the log, and no other instances of this dialog can be created.
Adriani90 pushed a commit to Adriani90/nvda that referenced this pull request Mar 13, 2024
…zerHelper to decrease likelihood of circular references in NVDA's GUI (nvaccess#16079)

Related to nvaccess#16019

Summary of the issue:
BoxSizerHelper class stores a strong reference to its parent. When it is mistakenly assigned to a member of its parent a circular reference is created making it impossible for Python's garbage collector to destroy the dialog when it goes out of scope.

Description of user facing changes
Should not be noticeable.

Description of development approach
BoxSizerHelper now stores a weak reference to its parent.
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.

2 participants