Return-Path: X-Original-To: apmail-perl-modperl-archive@www.apache.org Delivered-To: apmail-perl-modperl-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 681C29E65 for ; Mon, 11 Jun 2012 16:39:48 +0000 (UTC) Received: (qmail 84750 invoked by uid 500); 11 Jun 2012 16:39:44 -0000 Delivered-To: apmail-perl-modperl-archive@perl.apache.org Received: (qmail 84504 invoked by uid 500); 11 Jun 2012 16:39:44 -0000 Mailing-List: contact modperl-help@perl.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: List-Id: Delivered-To: mailing list modperl@perl.apache.org Received: (qmail 84379 invoked by uid 99); 11 Jun 2012 16:39:44 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 11 Jun 2012 16:39:44 +0000 X-ASF-Spam-Status: No, hits=-0.0 required=5.0 tests=SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: local policy) Received: from [65.110.20.35] (HELO mail.inter-corporate.com) (65.110.20.35) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 11 Jun 2012 16:39:37 +0000 Received: from Spooler by mail.inter-corporate.com (Mercury/32 v4.62) ID MO001287; 11 Jun 2012 09:22:56 -0700 Received: from spooler by mail.inter-corporate.com (Mercury/32 v4.62); 11 Jun 2012 09:22:27 -0700 Received: from [10.88.0.10] (96.53.47.42) by mail.inter-corporate.com (Mercury/32 v4.62) with ESMTP ID MG001286; 11 Jun 2012 09:22:26 -0700 From: "Randolf Richardson" Organization: Inter-Corporate Computer & Network Services To: mod_perl list Date: Mon, 11 Jun 2012 09:39:06 -0700 MIME-Version: 1.0 Subject: Re: User abort/stop, modperl 2 and TCP FIN / RST? Reply-to: randolf@modperl.pl Message-ID: <4FD61F2A.23795.58C5666@randolf.modperl.pl> Priority: normal In-reply-to: <4FD5C8A3.5000308@ice-sa.com> References: , <4FD5C8A3.5000308@ice-sa.com> X-mailer: Pegasus Mail for Windows (4.63) Content-type: text/plain; charset=ISO-8859-1 Content-transfer-encoding: Quoted-printable Content-description: Mail message body X-Virus-Checked: Checked by ClamAV on apache.org > Peter Valdemar M=F8rch 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_Con= nections > > - 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 exce= ption > >> 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 ma= gic bullet here. > Think of the following : > The whole FIN, ACK, RST etc.. exchange concerns /one/ TCP connection, be= tween your browser > and whatever it is talking to directly. For example, a HTTP proxy serve= r, 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 t= he user at the > browser half a planet away presses the "stop" button, is /never/ going t= o be guaranteed. > I'm not saying that you cannot try to catch such a thing as early as pos= sible. > But if your ultimate aim is to find a way where instant detection is gua= ranteed, 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 client-side. 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: http://httpd.apache.org/docs/current/mod/core.html#keepalive http://httpd.apache.org/docs/current/mod/core.html#keepalivetimeout 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: http://httpd.apache.org/docs/current/mod/core.html#timeout Randolf Richardson - randolf@inter-corporate.com Inter-Corporate Computer & Network Services, Inc. Beautiful British Columbia, Canada http://www.inter-corporate.com/