-
Notifications
You must be signed in to change notification settings - Fork 28.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Disallow dispose during listener callback #114530
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall it seems reasonable to me to disallow dispose during callback execution.
assert(() { | ||
_debugDisposed = true; | ||
return true; | ||
}()); | ||
if (kFlutterMemoryAllocationsEnabled && _creationDispatched) { | ||
MemoryAllocations.instance.dispatchObjectDisposed(object: this); | ||
} | ||
print('dispose is called $_notificationCallStackDepth $_reentrantlyRemovedListeners, _debugDisposed $_debugDisposed'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops, thanks for catching it
@@ -49,6 +49,23 @@ class Counter with ChangeNotifier { | |||
} | |||
|
|||
void main() { | |||
testWidgets('ValueNotifier can not dispose in callback', (WidgetTester tester) async { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we test this for one level deeper on the ChangeNotifier as well?
@@ -321,14 +321,17 @@ class ChangeNotifier implements Listenable { | |||
@mustCallSuper | |||
void dispose() { | |||
assert(ChangeNotifier.debugAssertNotDisposed(this)); | |||
assert(_notificationCallStackDepth == 0 && _reentrantlyRemovedListeners == 0, 'dispose can not be called during listener callbacks'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given the error message, should we just assert on the _notificationCallStackDepth? That's the only thing that indicates callback execution, no?
_listeners = _emptyListeners; | ||
_reentrantlyRemovedListeners = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we assert that it is 0 above, this would be a no-op, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
with this, it won't crash in release build
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe leave that as a comment here for future readers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
surely it would still cause a crash? the notifyListeners
method is going to call _listeners[i]
with values of i
bigger than _emptyListeners.length
if it's in the middle of dispatching listeners.
The analyzer is unhappy. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
_listeners = _emptyListeners; | ||
_reentrantlyRemovedListeners = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe leave that as a comment here for future readers?
auto label is removed for flutter/flutter, pr: 114530, due to - The status or check suite Mac tool_tests_commands has failed. Please fix the issues identified (or deflake) before re-applying this label. |
57f7967
to
58821c7
Compare
@@ -321,6 +321,7 @@ class ChangeNotifier implements Listenable { | |||
@mustCallSuper | |||
void dispose() { | |||
assert(ChangeNotifier.debugAssertNotDisposed(this)); | |||
assert(_notificationCallStackDepth == 0, 'dispose can not be called during listener callbacks'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe 'The "dispose()" method on $this was called during the call to "notifyListeners()". This is likely to cause errors since it modifies the list of listeners while the list is being used.'
would be clearer?
FWIW, "can not" means that it is possible to not do something. "cannot" means that it is not possible to do something.
So "I can not eat candy because I have self-control, but I do eat it a lot" vs "I cannot eat candy because I am allergic, so I do not eat any."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done. I also removed the attempt to clean it up in case it is called in release mode. if we were to properly clean up, it would probably have performance impact given this class is used a lot.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
47c54bb
to
405752e
Compare
405752e
to
e835090
Compare
* 87cb150 InkResponse highlights can be updated (flutter/flutter#115635) * 10c039b ca5b2f31c Roll Skia from d693b4b9fe5e to ab054a88d7c7 (1 revision) (flutter/engine#37743) (flutter/flutter#115654) * 7fd3bb2 Roll Plugins from a2fa4e9 to b2fe01b (6 revisions) (flutter/flutter#115656) * 3a3a0db Disallow dispose during listener callback (flutter/flutter#114530) * ca78327 Fix `NavigationBar` ripple (flutter/flutter#115499) * 4593917 [flutter_tools] Pin package:archive and manual roll (flutter/flutter#115662) * 9807761 Tiny improvement of RouteSettings display (flutter/flutter#114481) * 2cb2e84 Add more InkWell tests (flutter/flutter#115634) * 24865ad Remove unneeded comparison to `double.nan` (flutter/flutter#115547) * d2e6dfe Fix formatting in BottomAppBar test (flutter/flutter#115520) * 22e1ac7 b32c3a307 Roll Skia from ab054a88d7c7 to 345bceacd298 (3 revisions) (flutter/engine#37745) (flutter/flutter#115658) * 01c1e8e Allows pushing page based route as pageless route (flutter/flutter#114362) * 0e57147 nav drawer (flutter/flutter#115668) * cf2c9f6 Remove package:image dependency (flutter/flutter#115674) * 46d868c Roll Flutter Engine from b32c3a307bb5 to 7a390f97c798 (14 revisions) (flutter/flutter#115672) * 0fc4a3e Revert "Remove package:image dependency (#115674)" (flutter/flutter#115680) * c69fbf1 a77dfaff3 Remove `Linux Web Engine` from recipes CQ (flutter/engine#37758) (flutter/flutter#115675) * c95b693 f81ac3b19 Fix glyph sampling overlap (flutter/engine#37764) (flutter/flutter#115683) * be0c3a7 cef11cb9a Roll Skia from 12f01bc5b57e to c53d8cf5b823 (4 revisions) (flutter/engine#37767) (flutter/flutter#115684) * ae18d7b 6da59402e Roll Skia from c53d8cf5b823 to 0c1fcbe97b1f (1 revision) (flutter/engine#37771) (flutter/flutter#115685) * a17b4c3 91bc694eb Roll Fuchsia Mac SDK from tklUfTsSOVKk49tYq... to UcfQiA4PBOCs_7GEK... (flutter/engine#37773) (flutter/flutter#115686) * 1bee357 2d5e0667e Roll Fuchsia Linux SDK from WdtwlLEce90PjFJ9z... to qc20R_3e8PoqMQWgw... (flutter/engine#37775) (flutter/flutter#115687) * 633d7ef 916fd798d Roll Skia from 0c1fcbe97b1f to ad354e712b96 (2 revisions) (flutter/engine#37776) (flutter/flutter#115689)
* Disallow dispose during listener callback * addressing comment * add comments to code * Addressing comments * fix test
* Disallow dispose during listener callback * addressing comment * add comments to code * Addressing comments * fix test
fixes #114224
I think this is the correct way to handle the lifecycle of change listenable, but this may be a hard breaking change that requires non trivial migration.
Pre-launch Checklist
///
).If you need help, consider asking for advice on the #hackers-new channel on Discord.