Re: User abort/stop, modperl 2 and TCP FIN / RST?
André Warnier <[email protected]>
| Newsgroups | gmane.comp.apache.mod-perl |
|---|---|
| Message-ID | <[email protected]> |
Peter Valdemar Mørch wrote:
> Hi,
>
> I'm trying to find out how to detect user hitting 'stop' aka 'abort'
> in modperl 2. I found documentation on how it works in modperl 1 (
> http://perl.apache.org/docs/1.0/guide/debug.html#Detecting_Aborted_Connections
> - short version: $r->print returns success and $r->connection->aborted
> tells whether user hit abort ).
>
> However, I've tested the situation to be quite different in modperl 2:
>
> When the user hits 'stop', the *second* $r->rflush() generates an exception
>> Apache2::RequestIO::rflush: (103) Software caused connection
> as long as ~ 100ms has passed between the two rflush-es.
>
> Here is my understanding of what happens:
>
> When the user hits 'stop' in the browser, the browser sends a TCP
> packet with the FIN flag set. Apache2/modperl doesn't react to that
> and $r->connection->aborted still returns false. A subsequent
> $r->print and $r->rflush works fine. Apache now sends whatever was
> printed to the browser. The browser now sends RST ("Hey, I really want
> to kill this connection!") to Apache and after that, $r->print still
> succeeds (returns true), but $r->rflush dies (because now the client
> has closed the socket hard). "Second" $r->rflush really means "the
> first $r->rflush after Apache received the client's 'RST' ", so if I
> issue many $r->print("foo"); $r->rflush() in quick succession they all
> pass. Around 100ms needs to pass between $r->rflush-es for the second
> $r->rflush to fail. If tested this with Firefox and Chromium.
>
> So: After the user hits 'stop', the second $r->rflush (requiring a
> delay) generates an exception that can be used to determine that the
> user has hit 'stop'.
>
> Have I understood this correctly? Is there any way I can get Apache to
> react to the first TCP FIN, and have $r->connection->aborted return
> true at that point? Or otherwise detect reliably when the user has hit
> 'stop' in modperl 2 without having to wait an additional
> server-client-server roundtrip time?
>
Hi.
Just my two cent, maybe just to dampen your expectations a little bit.
This topic is probably as old as the WWW itself, and there just is no magic bullet here.
Think of the following :
The whole FIN, ACK, RST etc.. exchange concerns /one/ TCP connection, between your browser
and whatever it is talking to directly. For example, a HTTP proxy server, or a firewall.
And then, this proxy/firewall has /another/ TCP connection with the next node in the chain
(which may be your webserver or still another intermediary, like a load-balancer e.g.).
And in-between, there are buffers and a lot of piping, and delays.
So, expecting your mod_perl script to be able to detect instantly when the user at the
browser half a planet away presses the "stop" button, is /never/ going to be guaranteed.
I'm not saying that you cannot try to catch such a thing as early as possible.
But if your ultimate aim is to find a way where instant detection is guaranteed, then give
it up. It is just not possible, given how the Internet, and TCP/IP and HTTP work.