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.) 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