randolf at modperl
Jun 11, 2012, 9:39 AM
Post #5 of 8
> Peter Valdemar Mørch wrote:
Re: User abort/stop, modperl 2 and TCP FIN / RST?
[In reply to]
> > 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?
> 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.
In addition to that, there is variation among web browser and smart
phone vendors in the way they tear down sockets. Some may close the
socket immediately (a good practice in my opinion), while others may
just let the resource get garbage collected or even have an unknown
bug that results in a temporary or permanent resource leak on the
The same problems can occur with proxy servers, and for localized
end-user products that intercept all traffic (e.g., for the purpose
of scanning for viruses or other suspicious activity) there can be
problems as well. I've seen big problems with long timeouts with
some of these client-side products where the server has lingering
connections after the QUIT phase with POP3 connections, and removing
the firewalling software resolved the problem (but this isn't a
solution that helps you because many users insist on running these
programs, are working at companies that require it, etc.).
Making sure you have adequate resources to handle the load on the
server-side is likely less time-consuming than figuring out how every
web browser does (and will) handle the user pressing the "Stop"
button behind-the-scenes, although the KeepAlive and KeepAliveTImeout
directives may be helpful to you:
Note: The KeepAliveTimeout directive is only available starting
with Apache HTTPd v2.3.2.
Have you've already experimented with the Timeout directive? If
not, then I suggest you start with this directive before using the
KeepAlive and KeepAliveTimeout directives:
Randolf Richardson - randolf [at] inter-corporate
Inter-Corporate Computer & Network Services, Inc.
Beautiful British Columbia, Canada