-
Notifications
You must be signed in to change notification settings - Fork 874
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
Fix ConcurrentModificationException in TestMethodController #6689
Conversation
the root of this issue is likely that modifiable collections are shared over the document properties. I believe the risk of CME is still there, it just moved from the edit: i haven't checked the access pattern yet, I don't know from where else the collections are accessed, one red flag is that the empty collection is added to the properties and modified afterwards, i suppose someone could listen on property changes and react while the method is still running. edit2: usages of the keys are: |
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.
possible way out is the copy on write pattern:
for write:
- defensive copy after
props.get
- modify defensive copy
- put update with
Collecitons.unmodifiableFoo(defensiveCopy)
into props
for read:
props.get
and read remains simple
or synchronized collections, but the client has to know that it is synchonized and use the lock. JDK has also copy-on-write lists and sets but no map I believe.
edit: lock-free copy-on-write works only reliably if there is only one writer, otherwise writes can be reset by concurrent writers.
@mbien Thanks for the review! It made me look what's upper on the road and found the one and only call to this method in |
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.
this might work, thanks!
We should revisit this for NB21 and either make the shared collections immutable, or find some other simple way of access control.
(at the very least it has to be documented in-code so that nobody optimizes the defensive copies away again :))
👍
|
I always forget that the |
They have the added benefit of being a no-op in cases where you stack defensive copies. |
Just happened to bump into this CME, while working on Jenkinsfile support. It seems this has been reported as #5148.
It seems the CME happens as the
methods
list is a live one passed over as parameter, so the collection can be changed during the time ofmethods.forEach(tm -> removed.remove(tm))
. The solution would be to copy that collection before do the remove work. Interestingly we do have a copy of right after that call, so a simple reorder would solve the issue. I've just replaced theforEach
call withkeySet().removeAll
as I think that reads better.Otherwise the change is trivial. If it does not make into NB20, then I'd rebase this for master.