tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Konstantin Preißer <>
Subject RE: Another Non-blocking IO Question
Date Wed, 27 Nov 2013 16:18:10 GMT
Hi Dan,

> -----Original Message-----
> From: Daniel Mikusa []
> Sent: Wednesday, November 27, 2013 1:48 PM
> To: Tomcat Users List
> Subject: Re: Another Non-blocking IO Question
> I'm seeing another issue with the same basic test though.  After I tested the
> previous changes and confirmed they worked, I increased the amount of
> data that the request was sending.
>     int rc = postUrl(true, new StaticBytesStreamer(5 * 1048576, 131072, 0),
> "http://localhost:" +
>                             getPort() + "/", new ByteChunk(), resHeaders, null);
> This uncovered a problem with my tests where I wasn't checking
> output.isReady() and I was able to fix that.  However after fixing that I'm
> getting another hang.
> In this case, this is what seems to happen...
> 1.) The test client sends 1441792 bytes of data
> 2.) onWritePossible is called, this in turn calls onDataAvailable and starts
> echoing data
> 2.) The test echoer is able to read and write back 696091 bytes successfully
> 3.) At this point there is more input to read, but the call to output.isReady()
> returns false and the initial call to onWritePossible finishes.
> 4.) I see a call to onDataAvailable from the container.  This checks the
> input.isReady() which is true, but output.isReady() is still false.  The call to
> onDataAvailable finishes.
> 5.) This is where the test hangs.
> At this point, I would have expected onWritePossible to be called again by
> the container, since calls to output.isReady() returned false.  I haven't had
> much luck debugging this further.
> Here's the updated test case.
> Any thoughts?

I'm not an expert in using non-blocking I/O with Servlet 3.1, but I can see two possible issues
with your test case:

1) Your test directly copies the ServletInputStream to the ServletOutputStream using a buffer
of 8 KB. Are you sure that the HTTP client which you use for uploading the data is reading
the response while still sending the request?

As far I can see, you are using TomcatBaseTest#postUrl() [1]. Having a quick look at this
method, it first writes the complete request body before starting the response. This would
explain the hang as the client is not reading from the response body, and Tomcat is not able
to write to the response, causing a Deadlock.

This also happened when I tried this with Firefox: It would wait until the request is completely
written before starting to read the response. (I would think that generally a HTTP client
can not be expected to simultaneously read the response and write the request.)

2) If I read correctly, when onAllDataRead() is called, you call asyncContext.complete();
without checking if sos.isReady() is true. This could mean that the AsyncContext is completed
before the last call to sos.write() has finished. When I tried this with Tomcat's NumberWriter
example, this meant that the browser did not receive all data - the last 8 KB block was missing.
When I changed the code to check if sos.isReady() before completing the AsyncContext (and
if it is false, wait for the next call to onWritePossible before completing), then the browser
received all of the sent data.

However, I do not know what the required behavior here is. Tomcat's ByteCounter example also
directly calls ac.complete() after writing to the response without checking sos.isReady(),
but because it is just a few bytes it probably is able to completely write the bytes before
sos.write() returns, do it doesn't have practical consequences.

Konstantin Preißer


To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message