Hello, I'm using Tomcat 6.0.14 and its CometProcessor to create a long running connection between an HTTP client and my server. The client posts requests to the server using chunked transfer encoding (each chunk is a complete XML request processed by the servlet).
I'm using a servlet that is heavily derived from the example[1] on Tomcat's website. I've found that this implementation blocks the worker thread - which I would not expect - if the client sends a complete chunk and then wait some time before sending the next chunk. I'm using the W3C specification[2] of a chunk: chunk-size CRLF chunk-data CRLF Surprisingly, if I send a chunk that does not include the last CRLF, then the CometProcessor works correctly and does not block. My analysis of the blocking condition follows: ChunkedInputFilter.doRead() reads everything in the chunk except the last CRLF. It defers reading of the last CRLF until the next read() call by setting needCRLFParse to true at line 157. Calling ChunkedInputFilter.available() before receiving new data will therefore return 2, because the CRLF at the end of the chunk have not yet been read. The implementation of org.apache.catalina.connector.InputBuffer.available() always delegates to coyoteRequest.getAvailable() (in my environment, state is not BYTE_STATE or CHAR_STATE during this call). // org.apache.catalina.connector.InputBuffer, ~ line 260 public int available() { int available = 0; if (state == BYTE_STATE) { available = bb.getLength(); } else if (state == CHAR_STATE) { available = cb.getLength(); } if (available == 0) { coyoteRequest.action(ActionCode.ACTION_AVAILABLE, null); available = (coyoteRequest.getAvailable() > 0) ? 1 : 0; // <--- delegates here } return available; } The value that is returned by coyoteRequest.getAvailable() is set by Http11NioProcessor (see processing of ActionCode.ACTION_AVAILABLE at line 1218) to the value returned by its inputBuffer.available(). This method delegates to the ChunkedInputFilter, which returns 2, indicating two available bytes (CR, LF). Ultimately the InputBuffer.available() method above returns 1, because coyoteRequest.getAvailable() returned a non-zero value. Because in.available() in the attached servlet is non-zero, the servlet calls read() again. This time the call blocks, because when it calls read ChunkedInputFilter.doRead() finishes reading the CRLF it has in its buffer, it calls parseChunkHeader which makes a blocking call to readBytes(). Is this misuse of CometProcessor? Is there best practice guidance for managing long running connections with multiple requests with Tomcat? Thanks, Chris [1]: http://tomcat.apache.org/tomcat-6.0-doc/aio.html [2]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1 --------------------------------------------------------------------- To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]