Author: msergeant
Date: Sat Jun 18 11:20:49 2005
New Revision: 435
Modified:
branches/high_perf/qpsmtpd
Log:
Support a flag for how many connections to accept in the accept loop
Modified: branches/high_perf/qpsmtpd
==============================================================================
--- branches/high_perf/qpsmtpd (original)
+++ branches/high_perf/qpsmtpd Sat Jun 18 11:20:49 2005
@@ -1,4 +1,4 @@
-#!/usr/bin/perl -w
+#!/usr/bin/perl
use lib "./lib";
BEGIN {
@@ -44,6 +44,7 @@ my $MAXCONN = 15; # max si
my $USER = 'smtpd'; # user to suid to
my $MAXCONNIP = 5; # max simultaneous connections from one IP
my $PAUSED = 0;
+my $NUMACCEPT = 20;
sub help {
print <<EOT;
@@ -58,6 +59,7 @@ Options:
-m, --max-from-ip M : limit connections from a single IP; default 5
-f, --forkmode : fork a child for each connection
-j, --procs J : spawn J processes; default 1
+ -a, --accept K : accept up to K conns per loop; default 20
-h, --help : this page
NB: -f and -j are mutually exclusive. If -f flag is not used the server uses
@@ -77,6 +79,7 @@ GetOptions(
'c|limit-connections=i' => \$MAXCONN,
'm|max-from-ip=i' => \$MAXCONNIP,
'u|user=s' => \$USER,
+ 'a|accept=i' => \$NUMACCEPT,
'h|help' => \&help,
) || help();
@@ -86,6 +89,7 @@ if ($LOCALADDR =~ /^([\d\w\-.]+)$/) { $L
if ($USER =~ /^([\w\-]+)$/) { $USER = $1 } else { &help }
if ($MAXCONN =~ /^(\d+)$/) { $MAXCONN = $1 } else { &help }
if ($PROCS =~ /^(\d+)$/) { $PROCS = $1 } else { &help }
+if ($NUMACCEPT =~ /^(\d+)$/) { $NUMACCEPT = $1 } else { &help }
$PROCS = 1 if $LineMode;
# This is a bit of a hack, but we get to approximate MAXCONN stuff when we
@@ -300,9 +304,7 @@ sub accept_handler {
$running = scalar keys %$descriptors;
}
- my $max = $MAXCONNIP ? 100 : 1000;
-
- for (1 .. $max) {
+ for (1 .. $NUMACCEPT) {
if ($running >= $MAXCONN) {
::log(LOGINFO,"Too many connections: $running >= $MAXCONN.");
return;
@@ -312,13 +314,22 @@ sub accept_handler {
}
}
+use Errno qw(EAGAIN EWOULDBLOCK);
+
sub _accept_handler {
my $running = shift;
-
+
my $csock = $SERVER->accept();
if (!$csock) {
# warn("accept() failed: $!");
return;
+ if ($! == EAGAIN || $! == EWOULDBLOCK) {
+ return;
+ }
+ else {
+ warn("accept() failed: $!");
+ return 1;
+ }
}
binmode($csock, ':raw');
@@ -331,6 +342,7 @@ sub _accept_handler {
if (!$LineMode) {
# multiplex mode
my $client = Qpsmtpd::PollServer->new($csock);
+ my $rem_ip = $client->peer_ip_string;
if ($PAUSED) {
$client->write("451 Sorry, this server is currently paused\r\n");
@@ -340,8 +352,7 @@ sub _accept_handler {
if ($MAXCONNIP) {
my $num_conn = 1; # seed with current value
- my $rem_ip = $client->peer_ip_string;
-
+
# If we for-loop directly over values %childstatus, a SIGCHLD
# can call REAPER and slip $rip out from under us. Causes
# "Use of freed value in iteration" under perl 5.8.4.
@@ -426,7 +437,7 @@ sub _accept_handler {
sub log {
my ($level,$message) = @_;
# $level not used yet. this is reimplemented from elsewhere anyway
- warn("$$ $message\n");
+ warn("$$ fd:? $message\n");
}
sub pause {