Looking at your code ...
private void synchronized doWrite() throws IOException
{
_buffer.flip();
byte[] tmpBuf = new byte[4096];
while(_os.isReady() && _buffer.hasRemaining())
{
int bytesNum = Math.min(tmpBuf.length, _buffer.remaining());
_buffer.get(tmpBuf, 0, bytesNum); <-- if this is the second
iteration, you can't do this, you don't tmpBuf anymore
_os.write(tmpBuf, 0, bytesNum); <-- first use of tmpBuf is now
"in-process"
}
_buffer.compact();
}
The behavior of Async I/O is tricky to manage.
See Simone's excellent talk/slides at
http://www.slideshare.net/SimoneBordet/servlet-31-async-io
The problem lies in your changing of the tmpBuf within the loop.
The first call to _os.write(tmpBuf, 0. bytesNum) means that buffer now
belongs to Jetty.
You can't change that buffer in the second iteration of the the loop.
You'd need a new buffer each iteration of the loop.
--
Joakim Erdfelt <[email protected]>
webtide.com <http://www.webtide.com/> - intalio.com/jetty
Expert advice, services and support from from the Jetty & CometD experts
eclipse.org/jetty - cometd.org
On Tue, Apr 14, 2015 at 1:54 PM, Michael Aaron <[email protected]> wrote:
> Hello,
>
> I have upgraded to jetty-all-9.2.10.v20150310, but the problem remains.
> What might be wrong? Does this exception mean usage error (my code
> attempting to write when isReady() is not true), or does this mean some
> internal problem of Jetty?
>
> Thanks,
> Michael
>
> On Mon, Apr 13, 2015 at 4:08 PM, Joakim Erdfelt <[email protected]>
> wrote:
>
>> Can you try again with at least 9.2.9?
>>
>> There's been a great deal of work (bug fixes and improvements) in the
>> state management of Async I/O with that release.
>>
>> Note that jetty 9.2.10 is also available.
>>
>> Also, more importantly, Jetty 9.2.7 is considered a vulnerable release,
>> security wise
>> <https://github.com/eclipse/jetty.project/blob/master/advisories/2015-02-24-httpparser-error-buffer-bleed.md>
>> .
>>
>>
>> --
>> Joakim Erdfelt <[email protected]>
>> webtide.com <http://www.webtide.com/> - intalio.com/jetty
>> Expert advice, services and support from from the Jetty & CometD experts
>> eclipse.org/jetty - cometd.org
>>
>> On Mon, Apr 13, 2015 at 4:00 PM, Michael Aaron <[email protected]>
>> wrote:
>>
>>> Hello,
>>>
>>> I'm using Async IO feature of Jetty 9 (9.2.7.v20150116). I have some
>>> code to write a response, whose body is asynchronously generated.
>>>
>>> Here is how I got lost. In my code, ServletOutputStream.write() is
>>> called only if isReady() returns true. However, one of my test (server
>>> echoes back 1GB request which is also received using AsyncIO) failed for
>>> most of times due to IllegalStateException. Most likely it's because of
>>> "State=UNREADY"; very occasionally (I've only seen a few times), it would
>>> even fail with "State=READY", which makes me even more confused. The even
>>> trickier part is that if I ran another test before the failed test, it most
>>> likely would succeed...
>>>
>>> Can you enlighten me how what might be wrong?Any hint is appreciated.
>>>
>>> Thanks,
>>> Michael
>>>
>>> The code that does the write looks like this (_buffer is populated
>>> asynchrously, _os is ServletOutputStream):
>>>
>>> // To be called at onWritePossible() of WriteListener or when _buffer is
>>> populated asynchronously (i.e. previously we stopped write because _buffer
>>> is empty; _os.isReady() might still be true then)
>>>
>>> private void synchronized doWrite() throws IOException
>>> {
>>> _buffer.flip();
>>> byte[] tmpBuf = new byte[4096];
>>> while(_os.isReady() && _buffer.hasRemaining())
>>> {
>>> int bytesNum = Math.min(tmpBuf.length, _buffer.remaining());
>>> _buffer.get(tmpBuf, 0, bytesNum);
>>> // this is the only place we write to ServletOutputStream
>>> _os.write(tmpBuf, 0, bytesNum);
>>> }
>>> _buffer.compact();
>>> }
>>>
>>> =========== Stack trace that failed with UNREADY state =========
>>>
>>> 2015-04-13 14:30:05.665 HttpChannel [WARN] /echo
>>> java.lang.RuntimeException:
>>> at
>>>
>>> org.example.transport.http.server.AsyncIOResponseHandler.onError(AsyncIOResponseHandler.java:53)
>>> at org.eclipse.jetty.server.HttpOutput.run(HttpOutput.java:792)
>>> at
>>> org.eclipse.jetty.server.handler.ContextHandler.handle(ContextHandler.java:1175)
>>> at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:365)
>>> at org.eclipse.jetty.server.HttpChannel.run(HttpChannel.java:261)
>>> at
>>> org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
>>> at
>>> org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
>>> at java.lang.Thread.run(Thread.java:745)
>>> Caused by: java.lang.IllegalStateException: state=UNREADY
>>> at org.eclipse.jetty.server.HttpOutput.run(HttpOutput.java:822)
>>> ... 6 more
>>>
>>> 2015-04-13 14:30:05.665 SelectorManager [WARN] Could not process key for
>>> channel java.nio.channels.SocketChannel[connected local=/127.0.0.1:8099
>>> remote=/127.0.0.1:58960]
>>> java.lang.IllegalStateException
>>> at
>>> org.eclipse.jetty.server.HttpOutput$AsyncICB.onCompleteSuccess(HttpOutput.java:858)
>>> at
>>> org.eclipse.jetty.server.HttpOutput$AsyncWrite.onCompleteSuccess(HttpOutput.java:988)
>>> at
>>> org.eclipse.jetty.util.IteratingCallback.processing(IteratingCallback.java:300)
>>> at
>>> org.eclipse.jetty.util.IteratingCallback.succeeded(IteratingCallback.java:367)
>>> at
>>> org.eclipse.jetty.server.HttpConnection$SendCallback.onCompleteSuccess(HttpConnection.java:716)
>>> at
>>> org.eclipse.jetty.util.IteratingCallback.processing(IteratingCallback.java:300
>>> at
>>> org.eclipse.jetty.util.IteratingCallback.succeeded(IteratingCallback.java:367)
>>> at
>>> org.eclipse.jetty.io.WriteFlusher$PendingState.complete(WriteFlusher.java:270)
>>> at org.eclipse.jetty.io.WriteFlusher.completeWrite(WriteFlusher.java:383)
>>> at
>>> org.eclipse.jetty.io.SelectChannelEndPoint.onSelected(SelectChannelEndPoint.java:111)
>>> at
>>> org.eclipse.jetty.io.SelectorManager$ManagedSelector.processKey(SelectorManager.java:636
>>> at
>>> org.eclipse.jetty.io.SelectorManager$ManagedSelector.select(SelectorManager.java:607)
>>> at
>>> org.eclipse.jetty.io.SelectorManager$ManagedSelector.run(SelectorManager.java:545)
>>> at
>>> org.eclipse.jetty.util.thread.NonBlockingThread.run(NonBlockingThread.java:52)
>>> at
>>> org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
>>> at
>>> org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
>>> at java.lang.Thread.run(Thread.java:745)
>>>
>>>
>>> =========== Stack trace that failed with UNREADY state =========
>>> 2015-04-13 14:59:04.825 HttpChannel [WARN] /echo
>>> java.lang.RuntimeException:
>>> at
>>> org.example.transport.http.server.AsyncIOResponseHandler.onError(AsyncIOResponseHandler.java:53)
>>> at org.eclipse.jetty.server.HttpOutput.run(HttpOutput.java:792)
>>> at
>>> org.eclipse.jetty.server.handler.ContextHandler.handle(ContextHandler.java:1175)
>>> at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:365)
>>> at org.eclipse.jetty.server.HttpChannel.run(HttpChannel.java:261)
>>> at
>>> org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
>>> at
>>> org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
>>> at java.lang.Thread.run(Thread.java:745)
>>> Caused by: java.lang.IllegalStateException: state=READY
>>> at org.eclipse.jetty.server.HttpOutput.run(HttpOutput.java:822)
>>>
>>> ... 6 more
>>>
>>> _______________________________________________
>>> jetty-users mailing list
>>> [email protected]
>>> To change your delivery options, retrieve your password, or unsubscribe
>>> from this list, visit
>>> https://dev.eclipse.org/mailman/listinfo/jetty-users
>>>
>>
>>
>> _______________________________________________
>> jetty-users mailing list
>> [email protected]
>> To change your delivery options, retrieve your password, or unsubscribe
>> from this list, visit
>> https://dev.eclipse.org/mailman/listinfo/jetty-users
>>
>
>
> _______________________________________________
> jetty-users mailing list
> [email protected]
> To change your delivery options, retrieve your password, or unsubscribe
> from this list, visit
> https://dev.eclipse.org/mailman/listinfo/jetty-users
>
_______________________________________________
jetty-users mailing list
[email protected]
To change your delivery options, retrieve your password, or unsubscribe from
this list, visit
https://dev.eclipse.org/mailman/listinfo/jetty-users