On Nov 27, 2013, at 11:47 AM, Daniel Mikusa <dmik...@gopivotal.com> wrote:

> On Nov 27, 2013, at 11:18 AM, Konstantin Preißer <kpreis...@apache.org> wrote:
> 
>> Hi Dan,
>> 
>>> -----Original Message-----
>>> From: Daniel Mikusa [mailto:dmik...@gopivotal.com]
>>> 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.
>>> 
>>>  https://gist.github.com/dmikusa-pivotal/7660005
>>> 
>>> 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.)
> 
> I had a similar thought, so I'm glad to hear you mention it as well.  I'll 
> definitely have to investigate further.

This was the issue and in hindsight it makes sense as HTTP is a request then 
response based protocol.  Thanks for the pointer!

Dan

> 
> 
>> 
>> 
>> 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.
>> 
>> 
>> Regards,
>> Konstantin Preißer
>> 
>> 
>> [1] 
>> http://svn.apache.org/repos/asf/tomcat/trunk/test/org/apache/catalina/startup/TomcatBaseTest.java
>> 
>> 
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
>> For additional commands, e-mail: users-h...@tomcat.apache.org
>> 
> 


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

Reply via email to