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
Prevent CME in LaunchBarManager #263
Conversation
I'm not sure this is the best change, it adds a lot of code and there are other collections in Maybe a better option is to make |
This change synchronizes access to LaunchBarManager.descriptors, to avoid a ConcurrentModificationException when adding descriptors for 2 launches at the same time. Fixes: eclipse-cdt#262
Failed test is unrelated, see #259 |
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.
Can we simply change the maps to ConcurrentHashMap
or wrap it in Collections.synchronizedMap
(for the linked one)? That would mean that future editors of the code won't need to worry about getting it right as it would "just work" (moreso for concurrent hash map, less so for wrapper synchronized map)? That would address your other issues. I don't think there is a performance issue in the code of having concurrent hash maps.
I am happy with this change as is, but I'll hold off merging until you have a chance to consider my question.
isContained = descriptors.containsValue(descriptor); | ||
} | ||
if (!isContained) { | ||
throw new IllegalStateException(Messages.LaunchBarManager_1); |
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.
I am pretty sure you don't need to save off the isContained
here, I think throwing from within the synchronized block is fine:
syncrhonized(descriptors) {
if (descriptor != null && !descriptors.containsValue(descriptor)) {
throw new IllegalStateException(Messages.LaunchBarManager_1);
}
}
If you need to optimize to not get the lock if descriptor == null
then a partial split is fine too:
if (descriptor != null) {
syncrhonized(descriptors) {
if (!descriptors.containsValue(descriptor)) {
throw new IllegalStateException(Messages.LaunchBarManager_1);
}
}
}
...bar/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/internal/LaunchBarManager.java
Show resolved
Hide resolved
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.
I'm going to approve these changes as they are now. Fixing up the code more widely can be a discussion for another day, but this change is a move in the right direction.
Sorry I must have missed the e-mail notification for this comment. I actually thought about making the container a synchronized one, but there are operations in What I can do of course is keep the operations as they are, but wrap only the more complicated sequences with synchronized blocks. That will already reduce the amount of added code for this change. My bigger concern was that synchronizing only on the one map here might not be solving race condition problems, just hiding the CMEs. As I've commented at the start of the PR. But since the change got merged I'll look into cleaning the code a bit. I guess better to not have the CMEs, even if not all problems are solved. |
Your explanation is good, thanks for taking the time to document it out.
I agree. |
This change synchronizes access to
LaunchBarManager.descriptors
, to avoid aConcurrentModificationException
when adding descriptors for 2 launches at the same time.Fixes: #262