Chris,

Christopher Schultz-2 wrote
>> I'm running a tomcat 8.5.23 instance on ubuntu 16.04 (spring boot 
>> application with embedded tomcat) configured with 2 connectors: 
>> Http11NioProtocol and AjpNioProtocol. The AJP one is accessed
>> through an apache2 instance configured with mod_jk.It all works
>> well in the normal use case.
>> 
>> The application has code to look for the EOFExceptions during read
>> e.g. the client aborts the request which works well with HTTP but
>> not AJP. In my test I'm simulating this by closing the connection
>> half way through (some headers have been sent but no body)
>> 
>> The problem I'm seeing is an inconsistent behaviour for 
>> CoyoteInputStream.read() The HTTP connector throws an EOFException
>> in this case while the AJP one just returns -1.
>> 
>> The relevant call stack is this at 
>> org.apache.coyote.ajp.AjpProcessor.refillReadBuffer(AjpProcessor.java:
> 684)
>>
>> 
> at
>> org.apache.coyote.ajp.AjpProcessor$SocketInputBuffer.doRead(AjpProcess
> or.java:1433)
>>
>> 
> at org.apache.coyote.Request.doRead(Request.java:581)
>> at 
>> org.apache.catalina.connector.InputBuffer.realReadBytes(InputBuffer.ja
> va:326)
>>
>> 
> at
>> org.apache.catalina.connector.InputBuffer.checkByteBufferEof(InputBuff
> er.java:642)
>>
>> 
> at
>> org.apache.catalina.connector.InputBuffer.readByte(InputBuffer.java:33
> 7)
>>
>> 
> at
>> org.apache.catalina.connector.CoyoteInputStream.read(CoyoteInputStream
> .java:93)
>>
>>  Now based on this old and unrelated thread 
>> https://mail-archives.apache.org/mod_mbox/tomcat-users/201312.mbox/%3C

> 15FF6F04-B4C9-4D9B-B1B3-5C10CA955AEE@

> %3E
>>
>> 
> I understand that the AJP connector is perfectly capable of raising an
>> EOFException but it's just not doing that for me.
>> 
>> The documentation
>> https://tomcat.apache.org/tomcat-8.0-doc/config/ajp.html does not
>> suggest I need to do anything special.
>> 
>> I guess it's possible that this has something to do with the way
>> apache2 talks to the AJP connector. Any help is appreciated.
> 
> Interesting.
> 
> If your servlet simply reads the InputStream like this, you don't get
> an EOFException?
> 
> ServletInputStream in = request.getInputStream();
> for(;;)
>   in.read();
> 
> What part of the Servlet specification or Servlet API leads you to
> believe that EOFException should be thrown when the request has been
> completely read (or has been truncated, and no further data is available
> )?
> 
> I don't see anything to suggest that such behavior is either required
> or expected.
> 
> In fact, I'm surprised that the HTTP connector throws an EOFException
> instead of simply returning -1 like the API says it should.
> 
> - -chris

Let me first correct something I've said earlier:

HTTP Connector will actually throw an IOException when ssl unwrap fails
(rather than an EOFException) in
  at
org.apache.tomcat.util.net.SecureNioChannel.read(SecureNioChannel.java:618)
  at
org.apache.tomcat.util.net.NioBlockingSelector.read(NioBlockingSelector.java:173)
  at
org.apache.tomcat.util.net.NioSelectorPool.read(NioSelectorPool.java:235)
  at
org.apache.tomcat.util.net.NioSelectorPool.read(NioSelectorPool.java:216)
  at
org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.fillReadBuffer(NioEndpoint.java:1241)
  at
org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.read(NioEndpoint.java:1190)
  at
org.apache.coyote.http11.Http11InputBuffer.fill(Http11InputBuffer.java:717)
  at
org.apache.coyote.http11.Http11InputBuffer.access$300(Http11InputBuffer.java:40)
  at
org.apache.coyote.http11.Http11InputBuffer$SocketInputBuffer.doRead(Http11InputBuffer.java:1072)
  at
org.apache.coyote.http11.filters.IdentityInputFilter.doRead(IdentityInputFilter.java:140)
  at
org.apache.coyote.http11.Http11InputBuffer.doRead(Http11InputBuffer.java:261)
  at org.apache.coyote.Request.doRead(Request.java:581)
  at
org.apache.catalina.connector.InputBuffer.realReadBytes(InputBuffer.java:326)
  at
org.apache.catalina.connector.InputBuffer.checkByteBufferEof(InputBuffer.java:642)
  at
org.apache.catalina.connector.InputBuffer.readByte(InputBuffer.java:337)
  at
org.apache.catalina.connector.CoyoteInputStream.read(CoyoteInputStream.java:93)

while the AJP Connector returns -1. 

You're right I can't expect an EOFException, the API just mentions generic
IOException.
I guess my expectation comes from the fact that the HTTP Connector throws an
IOException on both read and write while the AJP one only throws a
java.io.IOException: Broken pipe exception on write but not on read where it
returns -1. 

I don't know the networking API well enough to say the behaviour is wrong,
just hoping I can get the AJP Connector to signal (via some IOException) on
read that something is unexpected.

Here's the relevant apache log
[Wed Jan 17 14:42:41 2018] [23791:140542260176640] [info]
ajp_service::jk_ajp_common.c (2773): (directory_service) sending request to
tomcat failed (unrecoverable), because of client read error (attempt=1)
[Wed Jan 17 14:42:41 2018] [23791:140542260176640] [debug]
ajp_reset_endpoint::jk_ajp_common.c (851): (directory_service) resetting
endpoint with socket 23 (socket shutdown)
[Wed Jan 17 14:42:41 2018] [23791:140542260176640] [debug]
ajp_abort_endpoint::jk_ajp_common.c (821): (directory_service) aborting
endpoint with socket 23
[Wed Jan 17 14:42:41 2018] [23791:140542260176640] [debug]
jk_shutdown_socket::jk_connect.c (932): About to shutdown socket 23
[127.0.0.1:42538 -> 127.0.0.1:15443]
[Wed Jan 17 14:42:41 2018] [23791:140542260176640] [debug]
jk_is_input_event::jk_connect.c (1383): timeout during poll on socket 23
[127.0.0.1:42538 -> 127.0.0.1:15443] (timeout=100)
[Wed Jan 17 14:42:41 2018] [23791:140542260176640] [debug]
jk_shutdown_socket::jk_connect.c (1016): Shutdown socket 23 [127.0.0.1:42538
-> 127.0.0.1:15443] and read 0 lingering bytes in 0 sec.
[Wed Jan 17 14:42:41 2018] [23791:140542260176640] [debug]
ajp_done::jk_ajp_common.c (3282): recycling connection pool for worker
directory_service and socket -1
[Wed Jan 17 14:42:41 2018] [23791:140542260176640] [debug]
jk_handler::mod_jk.c (2921): Consumed 0 bytes of remaining request data for
worker=directory_service
[Wed Jan 17 14:42:41 2018] [23791:140542260176640] [info]
jk_handler::mod_jk.c (2984): Aborting connection for
worker=directory_service

And tomcat log
[DEBUG] [ajp-nio-127.0.0.1-15443-exec-7] 14:42:41.067 AjpNioProtocol -
Processing socket
[org.apache.tomcat.util.net.NioChannel@517a280d:java.nio.channels.SocketChannel[connected
local=/127.0.0.1:15443 remote=/127.0.0.1:42538]] with status [OPEN_READ]
[DEBUG] [ajp-nio-127.0.0.1-15443-exec-7] 14:42:41.068 AjpNioProtocol - Found
processor [null] for socket
[org.apache.tomcat.util.net.NioChannel@517a280d:java.nio.channels.SocketChannel[connected
local=/127.0.0.1:15443 remote=/127.0.0.1:42538]]
[DEBUG] [ajp-nio-127.0.0.1-15443-exec-7] 14:42:41.068 AjpNioProtocol -
Popped processor [org.apache.coyote.ajp.AjpProcessor@1f4c1d25] from cache
[DEBUG] [ajp-nio-127.0.0.1-15443-exec-7] 14:46:38.078 AjpMessage - Received
979 18
[DEBUG] [ajp-nio-127.0.0.1-15443-exec-7] 14:46:39.578 AjpMessage - Received
2 18
// read data is processed here but there's no IOException on read. When I
try to write however I get a java.io.IOException: Broken pipe
[DEBUG] [ajp-nio-127.0.0.1-15443-exec-7] 14:46:40.717 AjpProcessor - Socket:
[org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@1be2c90:org.apache.tomcat.util.net.NioChannel@517a280d:java.nio.channels.SocketChannel[connected
local=/127.0.0.1:15443 remote=/127.0.0.1:42538]], Status in: [OPEN_READ],
State out: [CLOSED]
[DEBUG] [ajp-nio-127.0.0.1-15443-exec-7] 14:46:40.717 AjpNioProtocol -
Pushed Processor [org.apache.coyote.ajp.AjpProcessor@1f4c1d25]



--
Sent from: http://tomcat.10.x6.nabble.com/Tomcat-User-f1968778.html

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to