Skip to content
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 ConconcurrentModificationException in Maps #2210

Merged

Conversation

jonathanklee
Copy link
Contributor

Taxi G7 app was throwing this exception at startup.

It seems like Taxi G7 callbacks are adding new callbacks to execute.

@fynngodau
Copy link
Contributor

That the app was previously able to add callbacks was probably also a bug that is related to synchronization code. Without it fixed, as-is, (1) the callback would get executed from the list, (2) the app adds new callbacks during (1), and (3) afterwards the callbacks are cleared (L 874).

Do you know what callbacks the app added / what methods it called?

@jonathanklee
Copy link
Contributor Author

@fynngodau Yes I agree. The whole workflow seems a bit precarious as is. It seems like a callback is not being executed. I'll have a look at it.

@fynngodau
Copy link
Contributor

Generally speaking, I'm not even sure what the reason for the mapLock variable is. It could be replaced by this as the object that is synchronized at as far as I can tell.

@jonathanklee jonathanklee force-pushed the fix-concurrent-modification-exception branch from bc01996 to cf6e9a8 Compare February 28, 2024 08:14
@jonathanklee
Copy link
Contributor Author

@fynngodau I guess it's to have more granularity on the lock time since there are already synchronized(this) instructions in the class.

@mar-v-in mar-v-in added this to the 0.3.1 milestone Mar 3, 2024
}

copyList.add(callback)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this still all happen within one synchronized block? Otherwise, if getMapAsync is invoked twice at the same time, it may interleave in such a way that only one callback is stored.

Also, what would probably be much easier, would be to use the java.util.concurrent.CopyOnWriteArrayList - it handles this internally for you.

I do see the issue though, that if getMapAsync is invoked from within the map ready callback, that getMapAsync will never get it's callback invoked (as the clearing of the callback list is not tied to the actual list of callbacks that was invoked - that's not a new issue though). The better approach thus could be to change the calling code to create a copy of the list before invoking the callbacks, then clear the original list and then start invoking the callbacks from the copy. As the list that is iterated is a local copy, no ConcurrentModificationException could happen either and we wouldn't see the issue of callbacks getting never called.

Taxi G7 app was throwing this exception at startup.

It seems like Taxi G7 callbacks are adding new callbacks to execute.
@jonathanklee jonathanklee force-pushed the fix-concurrent-modification-exception branch from cf6e9a8 to 63a91c8 Compare March 4, 2024 12:20
@mar-v-in
Copy link
Member

mar-v-in commented Mar 4, 2024

Generally speaking, I'm not even sure what the reason for the mapLock variable is. It could be replaced by this as the object that is synchronized at as far as I can tell.

The motivation of using an explicit private lock is that it makes it impossible for code outside the class to acquire the lock. If you use this as a lock, everyone with a reference to the object can acquire the lock which may lead to unexpected and unwanted side effects.

That said, the usage of locks in this class specifically is probably not very consistent.

@mar-v-in mar-v-in merged commit ca02b77 into microg:master Mar 4, 2024
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants