Bug 59635 - PerMessageDeflate.sendMassagePart() IllegalArgumentException using atmosphere
Summary: PerMessageDeflate.sendMassagePart() IllegalArgumentException using atmosphere
Status: RESOLVED WORKSFORME
Alias: None
Product: Tomcat 8
Classification: Unclassified
Component: WebSocket (show other bugs)
Version: 8.0.33
Hardware: Macintosh All
: P2 major (vote)
Target Milestone: ----
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-05-25 15:07 UTC by Leon Kasparek
Modified: 2016-06-07 12:57 UTC (History)
0 users



Attachments
test case for described problem (186.34 KB, application/zip)
2016-05-30 14:09 UTC, Leon Kasparek
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Leon Kasparek 2016-05-25 15:07:37 UTC
Hi,
I have a problem since I have updated my Tomcat from version 8.0.32 to version 8.0.33.

I have a java maven project based on Wicket MVC, Atmosphere and Tomcat.

After the update to Tomcat 8.0.33 I get an IllegalArgumentException when I am sending an empty atmosphere message. The reason for this exception seems to be located in PerMessageDeflate.sendMessagePart(). I compared the method between both versions and found out that a change was made where the message is checked if it is empty. 
Following bug report should match to this change: https://bz.apache.org/bugzilla/show_bug.cgi?id=59189

Line 324 in PerMessageDeflate was changed from
"uncompressedPart.getPayload().limit() == 0"
to
"uncompressedPart.getPayload().limit() == 0 && uncompressedPart.isFin() && deflater.getBytesRead() == 0)"

It seems that now our empty message isn't handled like an empty message anymore, leeding to the following IllegalArgumentException:

java.lang.IllegalArgumentException
	at java.nio.Buffer.limit(Buffer.java:275) ~[?:1.8.0_74]
	at org.apache.tomcat.websocket.PerMessageDeflate.sendMessagePart(PerMessageDeflate.java:373) ~[tomcat-websocket.jar:8.0.33]
	at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessage(WsRemoteEndpointImplBase.java:300) ~[tomcat-websocket.jar:8.0.33]
	at org.apache.tomcat.websocket.WsRemoteEndpointImplBase$TextMessageSendHandler.write(WsRemoteEndpointImplBase.java:759) ~[tomcat-websocket.jar:8.0.33]
	at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendStringByCompletion(WsRemoteEndpointImplBase.java:216) ~[tomcat-websocket.jar:8.0.33]
	at org.apache.tomcat.websocket.WsRemoteEndpointAsync.sendText(WsRemoteEndpointAsync.java:47) ~[tomcat-websocket.jar:8.0.33]
	at org.atmosphere.container.version.JSR356WebSocket.write(JSR356WebSocket.java:73) ~[atmosphere-runtime-2.2.7.jar:2.2.7]
	at org.atmosphere.websocket.WebSocket.write(WebSocket.java:254) ~[atmosphere-runtime-2.2.7.jar:2.2.7]
	at org.atmosphere.websocket.WebSocket.write(WebSocket.java:219) ~[atmosphere-runtime-2.2.7.jar:2.2.7]
	at org.atmosphere.websocket.WebSocket.write(WebSocket.java:47) ~[atmosphere-runtime-2.2.7.jar:2.2.7]
	at org.atmosphere.cpr.AtmosphereResponse$2.write(AtmosphereResponse.java:531) ~[atmosphere-runtime-2.2.7.jar:2.2.7]
	at org.atmosphere.handler.AbstractReflectorAtmosphereHandler.onStateChange(AbstractReflectorAtmosphereHandler.java:148) ~[atmosphere-runtime-2.2.7.jar:2.2.7]
	at org.atmosphere.cpr.DefaultBroadcaster.invokeOnStateChange(DefaultBroadcaster.java:1074) [atmosphere-runtime-2.2.7.jar:2.2.7]
	at org.atmosphere.cpr.DefaultBroadcaster.prepareInvokeOnStateChange(DefaultBroadcaster.java:1094) [atmosphere-runtime-2.2.7.jar:2.2.7]
	at org.atmosphere.cpr.DefaultBroadcaster.executeAsyncWrite(DefaultBroadcaster.java:899) [atmosphere-runtime-2.2.7.jar:2.2.7]
	at org.atmosphere.cpr.DefaultBroadcaster$3.run(DefaultBroadcaster.java:520) [atmosphere-runtime-2.2.7.jar:2.2.7]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_74]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_74]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0_74]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0_74]
	at java.lang.Thread.run(Thread.java:745) [?:1.8.0_74]
Comment 1 Mark Thomas 2016-05-26 13:31:45 UTC
Bug 59189 is unlikely to be related to this report.

Bug 58414, r1703948 and r1732900 look more likely to be related.

Given that the unit tests pass and the Autobahn tests pass, this looks like some form of edge case. A simple test case that demonstrates the problem would be very helpful. I'll continue to look into this but if I can't reproduce this or discover the problem via code inspection, a test case will be required.
Comment 2 Leon Kasparek 2016-05-30 14:09:21 UTC
Created attachment 33901 [details]
test case for described problem

Thanks for the quick response,

I have created a small wicket-atmosphere-quickstart that represents the described problem.

It is a simple Wicket application, having one Homepage.
In WicketApplication.java I am setting the EventBus to use Websockets.
Also I am setting the max size per session to 20 kilobytes. This is important for the test case. 

The quickstart is a maven project, so you can simply deploy the war to your tomcat.

How to recreate the exception:
- Open multible tabs, ca. 10 (by opening multiple tabs, the session limit of 20 kilobytes will overfill and the pages will be removed from Wicket's Pagestore)
- now simply click "Sent Message"

The exception will occur after the message "Could not find a page with id '30' for session with id 'xxx' in the page stores. It will be unregistered", but only in Tomcat 8.0.0.33-35.
Comment 3 Mark Thomas 2016-06-06 12:52:41 UTC
The provided test case works without error with 9.0.x, 8.5.x, 8.0.x and the 8.0.33 tag.
Comment 4 Leon Kasparek 2016-06-07 12:33:47 UTC
Since the test case works fine for you, I made a video. 
The video shows exactly what I'm doing to avoid ambiguities or misunderstandings.

The video is too big to upload it here, so I have uploaded the video to following link: https://drive.google.com/file/d/0B4yjMTnPKTzWampXSEdTS0NWQmc/view?usp=sharing
The quality of the video should be better when you download it.

In the video I am starting a local Tomcat instance in my IntelliJ IDE.
It builds the project and deploys the war to my tomcat that runs on my localhost.

In the video you can also see that the described exception doesn't occur in Tomcat 8.0.32. 
I also tested newer versions and I still have the same behavior.

Thanks for your efforts.
Comment 5 Remy Maucherat 2016-06-07 12:45:11 UTC
A video is not a usable test case. Please don't reopen a report or a NEEDINFO issue without one.
Comment 6 Leon Kasparek 2016-06-07 12:57:58 UTC
The video was meant to be an additional instruction to the test case I have almost attached because the exception didn't occur when Mark tested it.