[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