Fix race in removing entities from the registry#110978
Merged
Merged
Conversation
There was a race here because `_async_registry_updated` would previously run in a task and `self.registry_entry` would not get unset soon enough so it would write unavailable state instead of removing the entity. I've seen this problem happen in production but I never could figure out why until now since its much more likely/reproducible as there are less tasks in play. Any time the `_async_registry_updated` ran after the `async_remove` task, the entity wouldn't get removed and the state would get written as unavailable instead because `self.registry_entry` hasn't been unset yet. To avoid this and not break the api (`self.async_removed_from_registry` might still need to access `self.registry_entry`) a new flag is added called `self._removed_from_registry`
20 tasks
If these tests fail they will not show anything other than AssertionError without the rewrite they are currently failing in #110978 and I have not been able to find the cause
Member
Author
|
Might have a better solution here. Need to sleep on it |
Member
Author
|
Better solution didn't pan out. The test here isn't great. I think we need another one that does the entity registry remove and than immediately simulates a config entry reload by resetting the platform. |
Member
Author
|
I think we can mark async_track_entity_registry_updated_event and the device registry to run immediately which should eliminate the call soon and make this completely race safe |
bdraco
commented
Feb 20, 2024
bdraco
commented
Feb 20, 2024
Member
Author
|
I think we can cleanup esphome entity removal quite a lot after this |
balloob
reviewed
Feb 21, 2024
balloob
approved these changes
Feb 21, 2024
bdraco
added a commit
that referenced
this pull request
Feb 21, 2024
Now that #110978 is fixed, we can remove most of entity removal code in ESPHome as deleting it from the registry will take care of removing the entity
20 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Proposed change
There was a race here because
_async_registry_updatedwould previously run in a task andself.registry_entrywould not get unset soon enough and theEntitybase class would write unavailable state instead of removing the entity.core/homeassistant/helpers/entity.py
Line 1366 in 9361f3c
I've seen this problem happen in production but I never could figure out why until now since its much more likely/reproducible as there are less tasks in play when working on #110967. Any time the
_async_registry_updatedran after theasync_removetask, the entity wouldn't get removed and the state would get written as unavailable instead becauseself.registry_entryhasn't been unset yet. To avoid this and not break the api (self.async_removed_from_registrymight still need to accessself.registry_entry) a new flag is added calledself._removed_from_registryType of change
Additional information
Checklist
ruff format homeassistant tests)If user exposed functionality or configuration variables are added/changed:
If the code communicates with devices, web services, or third-party tools:
Updated and included derived files by running:
python3 -m script.hassfest.requirements_all.txt.Updated by running
python3 -m script.gen_requirements_all..coveragerc.To help with the load of incoming pull requests: