-
Bug
-
Resolution: Duplicate
-
Minor
-
None
-
2.2.7.Final
-
None
-
-
undefined
We saw the following exception thrown in our application under heavy load:
java.util.ConcurrentModificationException
{{ at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:966)}}
{{ at java.util.LinkedList$ListItr.next(LinkedList.java:888)}}
{{ at java.util.AbstractCollection.toString(AbstractCollection.java:461)}}
{{ at io.undertow.server.protocol.framed.AbstractFramedChannel.toString(AbstractFramedChannel.java:1111)}}
This is the referenced source code: https://github.com/undertow-io/undertow/blob/e6e7fb78a1762bf584ef4324dac149860157ef3a/core/src/main/java/io/undertow/server/protocol/framed/AbstractFramedChannel.java#L1111
We believe the issue is that pendingFrames is a java.util.LinkedList, and that while pendingFrames.toString() is running in one thread, pendingFrames is being modified in another, and the java.util.ConcurrentModificationException is thrown.
As a java.util.ArrayDeque, heldFrames appears to be susceptible to the same race condition, but we haven't observed that yet in our application.
toString() is getting called by our code that converts WebSocketChannels to strings and logs them. We were able to work around the issue by boxing the WebSocketChannel objects logged by our application in a class with a safe toString().
We think it would be best if toString() was thread safe, which seems most easily accomplished by removing the calls to pendingFrames.toString() and heldFrames.toString(). Alternatively, pendingFrames and heldFrames could be converted to data structures more tolerant of concurrent access, but such a change would be considerably more invasive.
If a patch toward either of these (or some other) end is desirable, please let me know and I'll be happy to work on one.
Thank you for taking the time to review this issue.
- duplicates
-
UNDERTOW-1568 AbstractFramedChannel.toString() is not synchronized
- Resolved