[undertow-dev] dispatch and isDispatched do not agree

Stuart Douglas sdouglas at redhat.com
Tue Nov 22 17:02:52 EST 2016


That all sounds pretty much correct.

One thing to be aware of is that there is a difference between
dispatch(Runnable) and dispatch(HttpHandler), in that the HttpHandler
one will end the exchange when the call stack returns (unless it was
dispatched again). It sounds like the variant you want is the Runnable
one.

Stuart

On Wed, Nov 23, 2016 at 8:20 AM, Oliver Dain <oliver at analyticspot.com> wrote:
> Thanks for the clarification. I think I'm OK, but want to double check.
>
> I have some code that will pass an exchange object between thread pools not
> owned by Undertow. I can guarantee that I won't interact with the exchange
> from more than one thread at at time, but I will move it from thread pool to
> thread pool. For example, I might get a request and call dispatch. I'd then
> call a function that extracts a header from the exchange and then does an
> async lookup in a database for the info that was found in the header. When
> the DB lookup is complete I'll get a callback in a thread owned by the DB.
> In that callback I might extract another header from the exchange and then
> do another async lookup in a different database with a different thread
> pool. When that call is complete I'll get a callback in yet another thread,
> again not owned by Undertow. In that final callback I'd call
> "exchange.getResponseSender().send(...)" to send the final response.
>
> If I guarantee that I'm not operating on the exchange in more than one
> thread at a time I shouldn't have to worry about synchronization. However,
> since some async HttpServerExchange operations, like receiveFullBytes, can
> put me back on the Undertow IO pool I do need to check
> "exchange.isInIoThread()" and, if that returns true, I then need to call
> dispatch again.
>
> Does that all sound correct?
>
> On Tue, Nov 22, 2016 at 1:12 PM Stuart Douglas <sdouglas at redhat.com> wrote:
>>
>> On Wed, Nov 23, 2016 at 7:56 AM, Oliver Dain <oliver at analyticspot.com>
>> wrote:
>> > Wow! Thanks for the super-fast reply.
>> >
>> > I think I'm a little confused about the difference between being in an
>> > IO
>> > thread and being dispatched. Is it the case that if the server thinks
>> > I'm
>> > "not dispatched" (that is, if the server will send a response on my
>> > behalf
>> > when my method returns) that I'm always on an IO thread? I often do some
>> > work on my own thread pools and those threads often interact with the
>> > HttpServerExchange object. I know that some interactions with the
>> > exchange
>> > object (e.g. recieveFullBytes) will take an exchange that is in a
>> > dispatched
>> > state and put it in a non-dispatched state. So I want to just keep
>> > checking
>> > that I'm dispatched and, if I'm not, dispatch again. So my code might
>> > look
>> > something like:
>> >
>> > void handle(HttpServerExchange exchange) {
>> >     exchange.dispatch(myOwnThreadPoolExecutor, () -> {
>> >         log.info("I am not not on an IO thread and I am dispatched.");
>> >         doSomethingWithExchange(exchange);
>> >         assert exchange.isDispatched();
>> >         assert !exchange.isInIoThread();
>> >         // how do I check to see if I'm still in a dispatched state?
>> >     });
>> > }
>>
>> So the basic idea behind the 'dispatch' is that it is a way of
>> guaranteeing thread safety without needing to synchronize the exchange
>> object. Effectively it allows you to pass an exchange from one thread
>> to another in a way that guarantees that the first thread is 'done'
>> with the exchange before the second thread starts.
>>
>> >
>> > (note: the above is a bad, super-simplified example and in the actual
>> > code
>> > there's a lot of asynchronous stuff happening that bounces the execution
>> > from one thread pool to another).
>> >
>> > The reason for all of this is that I have some edge cases which appear
>> > to be
>> > race conditions in which I know for sure that I call exchange.dispatch()
>> > and
>> > then I start doing some work but the exchange gets ended before I've
>> > finished my computations and have a response to send leaving the client
>> > with
>> > an empty response. I'm not entirely sure how that could happen, but my
>> > best
>> > guess right now is that I interact with the exchange in some way that
>> > causes
>> > it to no longer be in in the dispatched state and, as a result, the
>> > HttpServerExchange is ending the exchange for me before I'm ready.
>>
>> I think I would need to look at a more specific example of what you
>> are doing, but it is possibly related to how you are handing stuff in
>> other threads? The exchange itself is not thread safe, if you start
>> doing work on the exchange in another thread without having dispatched
>> you can get a race condition.
>>
>> Stuart
>>
>> >
>> > Thanks again,
>> > Oliver
>> >
>> >
>> >
>> > On Tue, Nov 22, 2016 at 12:47 PM Stuart Douglas <sdouglas at redhat.com>
>> > wrote:
>> >>
>> >> After the call stack returns and the dispatch actually happens
>> >> isDispatched() will return false (allowing the exchange to be
>> >> dispatched again).
>> >>
>> >> In general you should not really need to check this anyway, if you
>> >> want to know if you are in the IO thread you should use isInIiThread()
>> >> instead.
>> >>
>> >> Stuart
>> >>
>> >> On Wed, Nov 23, 2016 at 7:44 AM, Oliver Dain <oliver at analyticspot.com>
>> >> wrote:
>> >> > I've got some pretty simple code that looks something like:
>> >> >
>> >> > if (!exhange.isDispatched()) {
>> >> >     exchange.dispatch(() -> {
>> >> >         assert exchange.isDispatched();
>> >> >          // more stuff....
>> >> >     });
>> >> > }
>> >> >
>> >> > but the assert fails. That is, when dispatch calls my runnable
>> >> > isDispatched
>> >> > is not true.
>> >> >
>> >> > I believe I have a bug somewhere with how/when dispatches are
>> >> > happening
>> >> > so
>> >> > I've littered my code with such asserts and they fail reliably even
>> >> > when
>> >> > I'm
>> >> > quite sure the exchange has been dispatched (e.g. when it is
>> >> > literally
>> >> > the
>> >> > first call in a Runnable passed to to the dispatch() method).
>> >> >
>> >> > What am I doing wrong?
>> >> > --
>> >> > CTO, Analytic Spot
>> >> > 44 West Broadway #222
>> >> > Eugene, OR 97401
>> >> > analyticspot.com • 425-296-6556
>> >> > www.linkedin.com/in/oliverdain
>> >> >
>> >> > _______________________________________________
>> >> > undertow-dev mailing list
>> >> > undertow-dev at lists.jboss.org
>> >> > https://lists.jboss.org/mailman/listinfo/undertow-dev
>> >
>> > --
>> > CTO, Analytic Spot
>> > 44 West Broadway #222
>> > Eugene, OR 97401
>> > analyticspot.com • 425-296-6556
>> > www.linkedin.com/in/oliverdain
>
> --
> CTO, Analytic Spot
> 44 West Broadway #222
> Eugene, OR 97401
> analyticspot.com • 425-296-6556
> www.linkedin.com/in/oliverdain



More information about the undertow-dev mailing list