Trying to use NIO connector instead of APR connector using Tomcat6 HEAD, I get an IllegalArgumentException while in a call to sendAck. Looking at InternalNioOutputBuffer.sendAck(), it uses ByteBuffer.wrap() to create a new ByteBuffer and uses this ByteBuffer in a call to writeToSocket. There is a check in SecureNioChannel.write() that the ByteBuffer is the one stored in the Commenting the line 372 in SecureNioChannel.java fixes the problem. //if ( src != bufHandler.getWriteBuffer() ) throw new IllegalArgumentException("You can only write using the application write buffer provided by the handler."); But I guess that the check is here for a valid reason, and a better fix would very likely consist in fixing the sendAck or in adding an "or" condition to the test for the case of sendAck(). GRAVE: Cannot find message associated with key standardWrapper.acknowledgeException java.lang.IllegalArgumentException: You can only write using the application write buffer provided by the handler. at org.apache.tomcat.util.net.SecureNioChannel.write(SecureNioChannel.java:372) at org.apache.tomcat.util.net.NioSelectorPool.write(NioSelectorPool.java:111) at org.apache.coyote.http11.InternalNioOutputBuffer.writeToSocket(InternalNioOutputBuffer.java:434) at org.apache.coyote.http11.InternalNioOutputBuffer.sendAck(InternalNioOutputBuffer.java:418) at org.apache.coyote.http11.Http11NioProcessor.action(Http11NioProcessor.java:1028) at org.apache.coyote.Response.action(Response.java:183) at org.apache.coyote.Response.acknowledge(Response.java:310) at org.apache.catalina.connector.Response.sendAcknowledgement(Response.java:1154) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:169) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:212) at org.apache.coyote.http11.Http11NioProcessor.process(Http11NioProcessor.java:888) at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:624) at org.apache.tomcat.util.net.NioEndpoint$Worker.run(NioEndpoint.java:1467) at java.lang.Thread.run(Thread.java:595)
Created attachment 19460 [details] A patch fixing the issue, but not meant to be a definitive patch Should fix this differently since it removes a useful check that is not valid in only one special case (sendAck call)
Patch is invalid and would lead to invalid SSL data being sent, bug is acknowledged and will be fixed.
The following fix has been applied Index: java/org/apache/tomcat/util/net/NioSelectorPool.java =================================================================== --- java/org/apache/tomcat/util/net/NioSelectorPool.java (revision 500888) +++ java/org/apache/tomcat/util/net/NioSelectorPool.java (working copy) @@ -103,6 +103,10 @@ boolean timedout = false; int keycount = 1; //assume we can write long time = System.currentTimeMillis(); //start the timeout timer + if ( socket.getBufHandler().getWriteBuffer()!= buf ) { + socket.getBufHandler().getWriteBuffer().put(buf); + buf = socket.getBufHandler().getWriteBuffer(); + } try { while ( (!timedout) && buf.hasRemaining() ) { if ( keycount > 0 ) { //only write if we were registered for a write