On 25/04/2013 13:20, Rossen Stoyanchev wrote:
> 
> ----- Original Message -----
>> From: "Mark Thomas" <ma...@apache.org>
>> To: "Tomcat Users List" <users@tomcat.apache.org>
>> Sent: Wednesday, April 24, 2013 2:14:53 PM
>> Subject: Re: AsyncListener.onError and disconnected client
>>
>> On 24/04/2013 18:38, Rossen Stoyanchev wrote:
>>>
>>> ----- Original Message -----
>>>> From: "Mark Thomas" <ma...@apache.org>
>>>> To: "Tomcat Users List" <users@tomcat.apache.org>
>>>> Sent: Wednesday, April 24, 2013 12:47:54 PM
>>>> Subject: Re: AsyncListener.onError and disconnected client
>>>>
>>>> On 24/04/2013 16:33, Rossen Stoyanchev wrote:
>>>>> Hi,
>>>>>
>>>>> I've seen various discussions here and on the web but I haven't
>>>>> found
>>>>> a conclusive answer. Why does an AsyncListener not receive
>>>>> onError
>>>>> notifications when a client disconnects?
>>>>
>>>> Because the Servlet EG says that is the required behaviour. The EG
>>>> is
>>>> currently revisiting that decision. See
>>>> https://java.net/jira/browse/SERVLET_SPEC-44
>>>
>>> Thanks for that reference. Is there something in the spec that
>>> explicitly makes requires this?
>>
>> Not that I am aware of which why I said "EG" rather than
>> "specification".
>>
>>> The JIRA ticket is about adding a "disconnect" callback but I can
>>> imagine in the very least, onComplete can be called. After the
>>> connection is over.
>>
>> onComplete should be called once the connection times out.
> 
> My understanding is that onComplete is always called regardless of how the 
> async request completed, i.e. following onTimeout, or onError. I would expect 
> it to be called after a client disconnect as well for consistency. Also I 
> wonder if a disconnect method is even needed? The onError method could be 
> called indicating that the "asynchronous operation has failed to complete" 
> (from the Javadoc). That's actually what I expected when I first tried.

It is. The issue is when is happens.

The issue is that there is no event (I am aware of) that the container
can monitor.

BIO - Only know once a read/write fails.

NIO - A current read/write will fail.
      The socket can be explicitly tested (but isn't currently)
      If the socket is in the poller I'd expect an error event
      If the socket was added to the poller I'd expect an error event

APR - A current read/write will fail.
      If the socket is in the poller I'd expect an error event
      If the socket was added to the poller I'd expect an error event
      It might be possible to test the socket but I haven't checked

There are times when a socket is not being used for read/write and is
not in a poller (e.g. when the app is doing some processing that doesn't
require output to the user agent). You won't get a notification of
disconnect in this case until the app has finished.

I wonder (for NIO and APR) if you could always have the socket in the
poller in order to detect a disconnect? You'd need to carefully keep
track of the registered interests for the socket and there are likely to
be threading issues as (currently) the Servlet spec is written on the
basis that there is only every one thread processing a socket at a time
(Tomcat's WebSocket impl violates that assumption - that is the subject
of another discussion).

>>>>> To my knowledge there is nothing inherent in NIO and TCP that
>>>>> prevents the server from detecting that the client has
>>>>> disconnected.
>>>>> The WebSocket implementation detects disconnected clients
>>>>> immediately
>>>>> and other HTTP servers (e.g. node) seem to be able to do this.
>>>>> What
>>>>> is it about the Servlet async support that prevents it from
>>>>> knowing
>>>>> when a client has disconnected?
>>>>
>>>> It would mean having to ditch the BIO connector / or not being
>>>> able
>>>> to pass the TCK (assuming the TCK tested this) when using the BIO
>>>> connector.
>>>
>>> I guess this goes back to the previous question about whether there
>>> is an explicit requirement and therefore test. Why would a TCK
>>> test explicitly check that disconnects are not communicated to
>>> AsyncListeners? Or is it a more indirect consequence of some other
>>> requirement?
>>
>> My point was that if a disconnect event was added to the spec then
>> the BIO connector could never be spec compliant.
> 
> If I understand correctly, you're saying the BIO connector can not detect a 
> client disconnect.

It can't until you try and read or write from the socket.

>> On reflection, it might not be that bad. The event could be fired
>> just not when the client disconnects. It would have to wait until an
>> attempt was made to read from / write to the socket.
> 
> That's actually not very different from the current situation where I catch 
> any exceptions while trying to write to the response and then call 
> asyncContext.complete(). I suppose it would make it more clear that a client 
> has disconnected (as opposed to some other error), but once writing to the 
> response has raised an error, it doesn't make a big difference what the error 
> is.

This really comes down to how the spec has been written. onError is for
errors that happen in the container during dispatch (i.e. at the end of
the async phase) that the app does not have visibility of. It allows the
container to tell the app that the request did not complete normally. It
is not intended for IO errors that happen during the async phase which
the app can just catch.

Mark


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to