[undertow-dev] dispatching from AsyncReceiverImpl.receivePartialBytes callback fails
Eldad Rudich
eldadru at gmail.com
Wed Mar 28 18:45:33 EDT 2018
Thanks,
Pausing IO is perfect for my use-case, from which context should I call the
Receiver#pause() method? within the PartialBytesCallback#handle() method?
should I always call pause() or just when handle() called from I/O thread?
Should I also call Receiver#resume() or it's automatically done by Undertow?
Eldad
On Thu, Mar 29, 2018 at 1:25 AM, Stuart Douglas <sdouglas at redhat.com> wrote:
> You need to call io.undertow.io.Receiver#pause() to pause the IO. This is
> so that you don't end up with multiple threads working on the exchange. If
> you don't want to pause (i.e. you hare happy to have more data keep coming
> and being processed while your blocking task is running) then you do this
> by just directly submitting the task to the worker, and not calling
> dispatch.
>
> This exists to keep Undertow's operation effectively single threaded, even
> though the exchange moves between threads one thread is always complete
> before the next one starts. If you do go with the second option of
> submitting to the worker you will need to come up with your own way of
> enforcing 'only one thread using the exchange'.
>
> Stuart
>
>
>
> On Thu, Mar 29, 2018 at 4:17 AM, Eldad Rudich <eldadru at gmail.com> wrote:
>
>> Hi,
>>
>> In order to read the content of the requests my HttpHandler
>> use receivePartialBytes as follows:
>>
>> public class AsyncReaderHttpHandler implements HttpHandler {
>>
>> @Override
>> public void handleRequest(HttpServerExchange exchange) throws Exception {
>>
>> if (exchange.isInIoThread()) {
>> exchange.dispatch(this);
>> return;
>> }
>>
>> readRequest(exchange);
>> }
>>
>> private void readRequest(HttpServerExchange exchange) {
>> exchange.getRequestReceiver().receivePartialBytes(new MyCallback());
>> }
>>
>> public class MyCallback implements PartialBytesCallback {
>>
>> @Override
>> public void handle(HttpServerExchange exchange, byte[] message, boolean last) {
>> if (exchange.isInIoThread()) {
>> exchange.dispatch(() -> handleData(exchange, message, last));
>> } else {
>> handleData(exchange, message, last);
>> }
>> }
>>
>> private void handleData(HttpServerExchange exchange, byte[] message, boolean last) {
>> // do some blocking operation with the data
>> }
>> }
>> }
>>
>> My handler dispatching to worker thread and than calls
>> receivePartialBytes() with a callback.
>>
>> At first, I thought that the handle() method of the callback will always
>> be called from a worker thread context.
>> I was surprised to discover that in some cases the callback will be
>> called from I/O thread (why?), so I had to add the second call to
>> dispatch() inside the callback.
>>
>> After adding the second call to dispatch() my code started to fail with:
>>
>> java.lang.IllegalStateException: UT000146: HttpServerExchange cannot
>> have both async IO resumed and dispatch() called in the same cycle
>> at io.undertow.server.HttpServerExchange$ReadDispatchChannel.re
>> sumeReads(HttpServerExchange.java:2100)
>> at io.undertow.io.AsyncReceiverImpl$5$2.handleRequest(AsyncRece
>> iverImpl.java:554)
>> at io.undertow.server.Connectors.executeRootHandler(Connectors.java:332)
>> at io.undertow.io.AsyncReceiverImpl$5.handleEvent(
>> AsyncReceiverImpl.java:549)
>> at io.undertow.io.AsyncReceiverImpl$5.handleEvent(
>> AsyncReceiverImpl.java:516)
>> at org.xnio.ChannelListeners.invokeChannelListener(ChannelListe
>> ners.java:92)
>> at io.undertow.channels.DetachableStreamSourceChannel$SetterDel
>> egatingListener.handleEvent(DetachableStreamSourceChannel.java:231)
>> at io.undertow.channels.DetachableStreamSourceChannel$SetterDel
>> egatingListener.handleEvent(DetachableStreamSourceChannel.java:218)
>> at org.xnio.ChannelListeners.invokeChannelListener(ChannelListe
>> ners.java:92)
>> at org.xnio.conduits.ReadReadyHandler$ChannelListenerHandler.re
>> adReady(ReadReadyHandler.java:66)
>> at org.xnio.nio.NioSocketConduit.handleReady(NioSocketConduit.java:88)
>> at org.xnio.nio.WorkerThread.run(WorkerThread.java:561)
>>
>>
>> What am I missing here? how can I use the asynchronous receiver and not
>> risking in blocking I/O thread?
>>
>> I'm using Undertow 1.4.19.Final.
>>
>> Thanks!
>>
>> _______________________________________________
>> undertow-dev mailing list
>> undertow-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/undertow-dev
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/undertow-dev/attachments/20180329/da074642/attachment-0001.html
More information about the undertow-dev
mailing list