Dear All,
I seem to be completely stuck with trying to detect client dropping connection, no matter how hard I try.
I start with a simple Perl script running as a standard CGI app:
#!/usr/bin/perl
use strict;
Log("$$: starting process");
$SIG{PIPE} = sub { Log("$$: PIPE!!"); };
$SIG{TERM} = sub { Log("$$: TERM!!"); };
$SIG{HUP} = sub { Log("$$: HUP"); };
$SIG{INT} = sub { Log("$$: INT"); };
Log("$$: Processing request");
print "\n\n";
for(1 .. 10)
{
Log("$$: Sleep $_ ");
sleep(1);
}
print "Content\n";
Log("$$: Done");
I also have tried the following modification of the script for mod_perl:
#!/usr/bin/perl
use strict;
use Apache2::RequestRec;
use Apache2::Connection;
Log("$$: starting process");
$SIG{PIPE} = sub { Log("$$: PIPE!!"); };
$SIG{TERM} = sub { Log("$$: TERM!!"); };
$SIG{HUP} = sub { Log("$$: HUP"); };
$SIG{INT} = sub { Log("$$: INT"); };
local our $Conn = Apache2::RequestRec->connection();
Log("$$: Processing request");
print "\n\n";
for(1 .. 10)
{
Log("$$: Sleep $_, aborted:", $Conn->aborted());
sleep(1);
}
print "Content\n";
Log("$$: Done");
and another modification for mod_fcgid (same idea with trying to intercept signals and both with and w/o trying to use Apache2::Connection).
Log() function just outputs messages to a log file, that i am tail -f 'ing.
I make a request using curl,
curl http://localhost/script.pl
and also have tried LWP::UserAgent.
The way I test it is run the request process (either curl or a simple .pl with a request made via LWP::UserAgent), and Control-C at some point (while watching 'Sleep XX' messages appear in the log file).
In all three cases with both LWP and curl i see the same behavior - no indication of a client dropping the connection (even with aborted() method of mod_perl) whatsoever, no signals, no messages about client dropping connection appearing in error.log of the server (LogLevel is set to 'info'), etc. The CGI process in CGI case doesn't get terminated and / or killed; it continues to loop and sleep until 10 seconds pass.
From what I have been able to find, I tried:
* Looks like adding print STDOUT in the loop should cause PIPE signal ('broken pipe'), I tried adding 'print STDOUT " "' right before sleep() call in the loop with no luck.
* Trying to see if the same print before sleep() would return failure ('print STDOUT " " or Log("Print failed!")', w/o any luck
* In mod_perl tests, trying to use Apache2::RequestRec->print() instead of print.
* LogLevel info should be giving me messages about clients dropping connections in error.log. I am not seeing any.
In addition, I clearly recall solving the same problem under mod_perl and Apache using $Conn->aborted() method, and it worked (but that was a different version of Apache 2 and mod_perl, unfortunately, I don’t have that env right now to compare…).
I have tried this on 2 versions of Apache and mod_perl,
* Ubuntu + apache 2.2.8 / mod_perl 2.0.3:
root@vmubuntu ~/api # apache2 -V
Server version: Apache/2.2.8 (Ubuntu)
Server built: Feb 2 2008 04:03:01
Server's Module Magic Number: 20051115:11
Server loaded: APR 1.2.11, APR-Util 1.2.12
Compiled using: APR 1.2.11, APR-Util 1.2.12
Architecture: 32-bit
Server MPM: Prefork
threaded: no
forked: yes (variable process count)
Server compiled with....
-D APACHE_MPM_DIR="server/mpm/prefork"
-D APR_HAS_SENDFILE
-D APR_HAS_MMAP
-D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
-D APR_USE_SYSVSEM_SERIALIZE
-D APR_USE_PTHREAD_SERIALIZE
-D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
-D APR_HAS_OTHER_CHILD
-D AP_HAVE_RELIABLE_PIPED_LOGS
-D DYNAMIC_MODULE_LIMIT=128
-D HTTPD_ROOT=""
-D SUEXEC_BIN="/usr/lib/apache2/suexec"
-D DEFAULT_PIDLOG="/var/run/apache2.pid"
-D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
-D DEFAULT_LOCKFILE="/var/run/apache2/accept.lock"
-D DEFAULT_ERRORLOG="logs/error_log"
-D AP_TYPES_CONFIG_FILE="/etc/apache2/mime.types"
-D SERVER_CONFIG_FILE="/etc/apache2/apache2.conf"
* Gentoo + apache 2.2.11 + mod_perl 2.0.4:
newcore tmp # apache2 -V
Server version: Apache/2.2.11 (Unix)
Server built: Oct 21 2009 16:42:25
Server's Module Magic Number: 20051115:21
Server loaded: APR 1.2.8, APR-Util 1.2.8
Compiled using: APR 1.2.8, APR-Util 1.2.8
Architecture: 32-bit
Server MPM: Prefork
threaded: no
forked: yes (variable process count)
Server compiled with....
-D APACHE_MPM_DIR="server/mpm/prefork"
-D APR_HAS_SENDFILE
-D APR_HAS_MMAP
-D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
-D APR_USE_SYSVSEM_SERIALIZE
-D APR_USE_PTHREAD_SERIALIZE
-D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
-D APR_HAS_OTHER_CHILD
-D AP_HAVE_RELIABLE_PIPED_LOGS
-D DYNAMIC_MODULE_LIMIT=128
-D HTTPD_ROOT="/usr"
-D SUEXEC_BIN="/usr/sbin/suexec"
-D DEFAULT_PIDLOG="/var/run/httpd.pid"
-D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
-D DEFAULT_LOCKFILE="/var/run/accept.lock"
-D DEFAULT_ERRORLOG="logs/error_log"
-D AP_TYPES_CONFIG_FILE="/etc/apache2/mime.types"
-D SERVER_CONFIG_FILE="/etc/apache2/httpd.conf"
As you can see, both servers are running prefork mpm.
Would anyone have a suggestion for this problem? Ideally I would like either to be able to somehow detect client dropping connection from his side from within the script, or Apache itself just killing the worker / CGI process whenever it detects that.
Fi.