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