|
|
Created:
4 years, 5 months ago by sof Modified:
4 years, 5 months ago Reviewers:
haraken, dominicc (has gone to gerrit) CC:
blink-reviews, blink-reviews-dom_chromium.org, chromium-reviews, dglazkov+blink, eae+blinkwatch, rwlbuis Base URL:
https://chromium.googlesource.com/chromium/src.git@master Target Ref:
refs/pending/heads/master Project:
chromium Visibility:
Public. |
DescriptionAvoid snapshotting ContextLifecycleObservers when iterating.
To allow safe iteration over the set of ExecutionContext observers,
a snapshot of the set was taken before iterating over it. So as to
allow observers to unregister themselves while being notified.
Apart from PostMessageTimer unregistering itself while being stop()ed,
the ContextLifecycleObservers do not mutate the observer set, hence
we can avoid the snapshot step and iterate directly over the observers.
Attempts to remove an observer while iterating is caught and
asserted for.
As the observer set is a set of weak references, some care is needed
to keep those references strong while iterating. That and other details
surrounding observer iteration is now handled by the auxiliary scope object
LifecycleNotifier<>::IterationScope.
Should the constraint of not being allowed to remove observers while
iterating prove too cumbersome, supporting lazy removal of observers
(post iteration) would be straightforward.
R=
BUG=451132
Committed: https://crrev.com/5b0b4e4f357e9348870dd5612b663a35894b49f3
Cr-Commit-Position: refs/heads/master@{#402141}
Patch Set 1 #Patch Set 2 : record removals when iterating stopped observers also #Patch Set 3 : avoid removing PostMessageTimers when stop-iterating #Patch Set 4 : just disallow all adds + removals during ContextLifecycleNotifier iterations #Patch Set 5 : tidy up further #Patch Set 6 : msvc compile fix.. #
Total comments: 5
Patch Set 7 : remove IterationScope, indirection not needed #
Created: 4 years, 5 months ago
Messages
Total messages: 26 (15 generated)
Description was changed from ========== Avoid snapshotting ContextLifecycleObserver when iterating. To allow safe iteration over the set of ExecutionContext observers, the set might be mutated while iterating, a snapshot is initially taken, and iteration happens over it. Avoid creating the snapshot by swapping out the observer set while iterating, restoring it on completion. To correctly handle any removals that are performed while iterating, we instead record those removals and remove them from the observer set at the end. As an experiment, we do not perform that last step while notifying observers that the ExecutionContext has entered a stopped state. R= BUG= ========== to ========== Avoid snapshotting ContextLifecycleObservers when iterating. To allow safe iteration over the set of ExecutionContext observers, the set might be mutated while iterating, a snapshot is initially taken, and iteration happens over it. Avoid creating the snapshot by swapping out the observer set while iterating, restoring it on completion. To correctly handle any removals that are performed while iterating, we instead record those removals and remove them from the observer set at the end. As an experiment, we do not perform that last step while notifying observers that the ExecutionContext has entered a stopped state. R= BUG= ==========
Description was changed from ========== Avoid snapshotting ContextLifecycleObservers when iterating. To allow safe iteration over the set of ExecutionContext observers, the set might be mutated while iterating, a snapshot is initially taken, and iteration happens over it. Avoid creating the snapshot by swapping out the observer set while iterating, restoring it on completion. To correctly handle any removals that are performed while iterating, we instead record those removals and remove them from the observer set at the end. As an experiment, we do not perform that last step while notifying observers that the ExecutionContext has entered a stopped state. R= BUG= ========== to ========== Avoid snapshotting ContextLifecycleObservers when iterating. To allow safe iteration over the set of ExecutionContext observers, the set might be mutated while iterating, a snapshot is initially taken, and iteration happens over it. Avoid creating the snapshot by swapping out the observer set while iterating, restoring it on completion. To correctly handle any removals that are performed while iterating, we instead record those removals and remove them from the observer set at the end. R= BUG= ==========
Description was changed from ========== Avoid snapshotting ContextLifecycleObservers when iterating. To allow safe iteration over the set of ExecutionContext observers, the set might be mutated while iterating, a snapshot is initially taken, and iteration happens over it. Avoid creating the snapshot by swapping out the observer set while iterating, restoring it on completion. To correctly handle any removals that are performed while iterating, we instead record those removals and remove them from the observer set at the end. R= BUG= ========== to ========== Avoid snapshotting ContextLifecycleObservers when iterating. To allow safe iteration over the set of ExecutionContext observers, the set might be mutated while iterating, a snapshot is initially taken and iteration happens over that snapshot. Avoid creating the snapshot by swapping out the observer set while iterating, restoring it on completion. Should an observer attempt to remove itself while being notified, this is now disallowed. The codebase appears ready for such a strict regime, but support for removals-while-iterating could be added should that prove to be too constraining. R= BUG= ==========
Patchset #6 (id:100001) has been deleted
Patchset #6 (id:120001) has been deleted
Patchset #6 (id:140001) has been deleted
Patchset #6 (id:160001) has been deleted
Patchset #5 (id:80001) has been deleted
Description was changed from ========== Avoid snapshotting ContextLifecycleObservers when iterating. To allow safe iteration over the set of ExecutionContext observers, the set might be mutated while iterating, a snapshot is initially taken and iteration happens over that snapshot. Avoid creating the snapshot by swapping out the observer set while iterating, restoring it on completion. Should an observer attempt to remove itself while being notified, this is now disallowed. The codebase appears ready for such a strict regime, but support for removals-while-iterating could be added should that prove to be too constraining. R= BUG= ========== to ========== Avoid snapshotting ContextLifecycleObservers when iterating. To allow safe iteration over the set of ExecutionContext observers, a snapshot of the set was taken before iterating over it. So as to allow observers to unregister themselves while being notified. Apart from PostMessageTimer unregistering itself while being stop()ed, the ContextLifecycleObservers do not mutate the observer set, hence we can avoid the snapshot step and iterate directly over the observers. Attempts to remove an observer while iterating is caught and asserted for. As the observer set is a set of weak references, some care is needed to keep those references strong while iterating. That and other details surrounding observer iteration is now handled by the auxiliary scope object LifecycleNotifier<>::IterationScope. Should the constraint of not being allowed to remove observers while iterating prove too cumbersome, supporting lazy removal of observers (post iteration) would be straightforward. R= BUG= ==========
Patchset #5 (id:180001) has been deleted
Description was changed from ========== Avoid snapshotting ContextLifecycleObservers when iterating. To allow safe iteration over the set of ExecutionContext observers, a snapshot of the set was taken before iterating over it. So as to allow observers to unregister themselves while being notified. Apart from PostMessageTimer unregistering itself while being stop()ed, the ContextLifecycleObservers do not mutate the observer set, hence we can avoid the snapshot step and iterate directly over the observers. Attempts to remove an observer while iterating is caught and asserted for. As the observer set is a set of weak references, some care is needed to keep those references strong while iterating. That and other details surrounding observer iteration is now handled by the auxiliary scope object LifecycleNotifier<>::IterationScope. Should the constraint of not being allowed to remove observers while iterating prove too cumbersome, supporting lazy removal of observers (post iteration) would be straightforward. R= BUG= ========== to ========== Avoid snapshotting ContextLifecycleObservers when iterating. To allow safe iteration over the set of ExecutionContext observers, a snapshot of the set was taken before iterating over it. So as to allow observers to unregister themselves while being notified. Apart from PostMessageTimer unregistering itself while being stop()ed, the ContextLifecycleObservers do not mutate the observer set, hence we can avoid the snapshot step and iterate directly over the observers. Attempts to remove an observer while iterating is caught and asserted for. As the observer set is a set of weak references, some care is needed to keep those references strong while iterating. That and other details surrounding observer iteration is now handled by the auxiliary scope object LifecycleNotifier<>::IterationScope. Should the constraint of not being allowed to remove observers while iterating prove too cumbersome, supporting lazy removal of observers (post iteration) would be straightforward. R= BUG=451132 ==========
sigbjornf@opera.com changed reviewers: + dominicc@chromium.org, haraken@chromium.org
please take a look.
Thank you for taking over https://codereview.chromium.org/2091023004 and cleaning up these FIXMEs? Are you now disallowing removal during ActiveDOMObject iteration where that was allowed before? Is that feasible? Could you clean up the duplication in the ActiveDOMObject notification? I think all of those methods are the same except for the call to the ActiveDOMObject.
LGTM with comments. https://codereview.chromium.org/2094143002/diff/170007/third_party/WebKit/Sou... File third_party/WebKit/Source/platform/LifecycleNotifier.h (right): https://codereview.chromium.org/2094143002/diff/170007/third_party/WebKit/Sou... third_party/WebKit/Source/platform/LifecycleNotifier.h:80: explicit IterationScope(LifecycleNotifier* notifier, IterationState allowable = AllowingNone) Is the second parameter used somewhere? https://codereview.chromium.org/2094143002/diff/170007/third_party/WebKit/Sou... third_party/WebKit/Source/platform/LifecycleNotifier.h:93: m_observers.swap(m_notifier->m_observers); I don't fully understand why we need to explicitly swap m_observers. The caller side holds an iterator while iterating the hash set. Wouldn't it be enough to keep the hash set alive?
https://codereview.chromium.org/2094143002/diff/170007/third_party/WebKit/Sou... File third_party/WebKit/Source/platform/LifecycleNotifier.h (right): https://codereview.chromium.org/2094143002/diff/170007/third_party/WebKit/Sou... third_party/WebKit/Source/platform/LifecycleNotifier.h:80: explicit IterationScope(LifecycleNotifier* notifier, IterationState allowable = AllowingNone) On 2016/06/27 01:06:34, haraken wrote: > > Is the second parameter used somewhere? Line 85 https://codereview.chromium.org/2094143002/diff/170007/third_party/WebKit/Sou... third_party/WebKit/Source/platform/LifecycleNotifier.h:93: m_observers.swap(m_notifier->m_observers); On 2016/06/27 01:06:34, haraken wrote: > > I don't fully understand why we need to explicitly swap m_observers. The caller > side holds an iterator while iterating the hash set. Wouldn't it be enough to > keep the hash set alive? > I was thinking about that overnight, this being too conservative. And looking at HeapTest.HeapWeakCollectionTypes, we can rely on iterators strongifying the collection. So let me simplify away IterationScope.
On 2016/06/27 00:44:00, dominicc wrote: > Thank you for taking over https://codereview.chromium.org/2091023004 and > cleaning up these FIXMEs? > I didn't consider the FIXMEs practical, but I'm now convinced that they are. > Are you now disallowing removal during ActiveDOMObject iteration where that was > allowed before? Is that feasible? Yes, apart from PostMessageTimer, the codebase does seem ready -- going through the other stop() overrides, I could only find local operations being performed, and no mutation of the notifier. So I think we should try to disallow removals - if that proves a step too far on the web, ps#2 is one way to allow removals while still avoiding snapshotting. > > Could you clean up the duplication in the ActiveDOMObject notification? I think > all of those methods are the same except for the call to the ActiveDOMObject. I'm not planning on factoring out those smaller loop bodies & provide an ActiveDOMObject-only iterator, at least not here.
Suggestions welcome for alternate naming of the IterationState enum tags. https://codereview.chromium.org/2094143002/diff/170007/third_party/WebKit/Sou... File third_party/WebKit/Source/platform/LifecycleNotifier.h (right): https://codereview.chromium.org/2094143002/diff/170007/third_party/WebKit/Sou... third_party/WebKit/Source/platform/LifecycleNotifier.h:93: m_observers.swap(m_notifier->m_observers); On 2016/06/27 05:14:14, sof wrote: > On 2016/06/27 01:06:34, haraken wrote: > > > > I don't fully understand why we need to explicitly swap m_observers. The > caller > > side holds an iterator while iterating the hash set. Wouldn't it be enough to > > keep the hash set alive? > > > > I was thinking about that overnight, this being too conservative. And looking at > HeapTest.HeapWeakCollectionTypes, we can rely on iterators strongifying the > collection. So let me simplify away IterationScope. Now done.
LGTM
Sorry for jumping in a bit on dominicc@'s efforts, but the possibility of removing all allocations during these iteration steps proved too tempting. I don't know if it would explain issue 451132, OOM avoidance would be the only reason why.(?)
The CQ bit was checked by sigbjornf@opera.com
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
Message was sent while issue was closed.
Description was changed from ========== Avoid snapshotting ContextLifecycleObservers when iterating. To allow safe iteration over the set of ExecutionContext observers, a snapshot of the set was taken before iterating over it. So as to allow observers to unregister themselves while being notified. Apart from PostMessageTimer unregistering itself while being stop()ed, the ContextLifecycleObservers do not mutate the observer set, hence we can avoid the snapshot step and iterate directly over the observers. Attempts to remove an observer while iterating is caught and asserted for. As the observer set is a set of weak references, some care is needed to keep those references strong while iterating. That and other details surrounding observer iteration is now handled by the auxiliary scope object LifecycleNotifier<>::IterationScope. Should the constraint of not being allowed to remove observers while iterating prove too cumbersome, supporting lazy removal of observers (post iteration) would be straightforward. R= BUG=451132 ========== to ========== Avoid snapshotting ContextLifecycleObservers when iterating. To allow safe iteration over the set of ExecutionContext observers, a snapshot of the set was taken before iterating over it. So as to allow observers to unregister themselves while being notified. Apart from PostMessageTimer unregistering itself while being stop()ed, the ContextLifecycleObservers do not mutate the observer set, hence we can avoid the snapshot step and iterate directly over the observers. Attempts to remove an observer while iterating is caught and asserted for. As the observer set is a set of weak references, some care is needed to keep those references strong while iterating. That and other details surrounding observer iteration is now handled by the auxiliary scope object LifecycleNotifier<>::IterationScope. Should the constraint of not being allowed to remove observers while iterating prove too cumbersome, supporting lazy removal of observers (post iteration) would be straightforward. R= BUG=451132 ==========
Message was sent while issue was closed.
Committed patchset #7 (id:230001)
Message was sent while issue was closed.
Description was changed from ========== Avoid snapshotting ContextLifecycleObservers when iterating. To allow safe iteration over the set of ExecutionContext observers, a snapshot of the set was taken before iterating over it. So as to allow observers to unregister themselves while being notified. Apart from PostMessageTimer unregistering itself while being stop()ed, the ContextLifecycleObservers do not mutate the observer set, hence we can avoid the snapshot step and iterate directly over the observers. Attempts to remove an observer while iterating is caught and asserted for. As the observer set is a set of weak references, some care is needed to keep those references strong while iterating. That and other details surrounding observer iteration is now handled by the auxiliary scope object LifecycleNotifier<>::IterationScope. Should the constraint of not being allowed to remove observers while iterating prove too cumbersome, supporting lazy removal of observers (post iteration) would be straightforward. R= BUG=451132 ========== to ========== Avoid snapshotting ContextLifecycleObservers when iterating. To allow safe iteration over the set of ExecutionContext observers, a snapshot of the set was taken before iterating over it. So as to allow observers to unregister themselves while being notified. Apart from PostMessageTimer unregistering itself while being stop()ed, the ContextLifecycleObservers do not mutate the observer set, hence we can avoid the snapshot step and iterate directly over the observers. Attempts to remove an observer while iterating is caught and asserted for. As the observer set is a set of weak references, some care is needed to keep those references strong while iterating. That and other details surrounding observer iteration is now handled by the auxiliary scope object LifecycleNotifier<>::IterationScope. Should the constraint of not being allowed to remove observers while iterating prove too cumbersome, supporting lazy removal of observers (post iteration) would be straightforward. R= BUG=451132 Committed: https://crrev.com/5b0b4e4f357e9348870dd5612b663a35894b49f3 Cr-Commit-Position: refs/heads/master@{#402141} ==========
Message was sent while issue was closed.
Patchset 7 (id:??) landed as https://crrev.com/5b0b4e4f357e9348870dd5612b663a35894b49f3 Cr-Commit-Position: refs/heads/master@{#402141} |