Hi

I am facing problem in the following scenario:

In response to an upgrade request I do upgrade, get WebConnection instance,
take UpgradedServletInputStream from it
As far it is a usual ServletInputStream I set ReadListener on it. It works
almost properly so I didn't notice it for long. Now I see that unlike usual
non-upgraded input stream, UpgradedServletInputStream does invoke
onDataAvailable infinitely until I consume all arrived bytes. For example
in the case if I simply ignore onDataAvailable invocation then the
container will invoke it infinitely (does busy wait).

After reading source code I discovered that the difference between a
regular CoyoteInputStream (with InputBuffer inside) and
UpgradedServletInputStream is that they are processed by different
Processor implementations.

When a selector fires OPEN_READ event it will pass it to
AbstractProtocol.process that invokes processor (that invokes
onDataAvailable through several layers). After that in both cases (regular
and upgraded) AbstractProtocol does invoke longPoll (see if/elseif for LONG
and UPGRADED, lines ~ 820 - 850) that looks like this:

protected void longPoll(SocketWrapperBase<?> socket, Processor processor) {
    if (!processor.isAsync()) {
        socket.registerReadInterest();
    }
}

Here is the difference: in case of regular non-upgraded request in async
mode processor will return isAsync() = true because processor =
Http11Processor. However upgraded requests are processed with processor =
UpgradeProcessorExternal that will always return false and we setup read
interest again.
This is the reason we get onDataAvailable again and again as we always
setup read interest.

The only workaround is to block inside onDataAvailable to wait until all
received bytes will be processed however it is dangerous as it may lead to
deadlock as we block inside of async processing loop.

Are there any suggestions what can be done to get it work properly?

Reply via email to