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.

Reply via email to