]> git.pld-linux.org Git - packages/spamassassin.git/commitdiff
- obsolete
authorJakub Bogusz <qboosh@pld-linux.org>
Wed, 5 Oct 2005 10:15:31 +0000 (10:15 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    spamassassin-prefork.patch -> 1.2

spamassassin-prefork.patch [deleted file]

diff --git a/spamassassin-prefork.patch b/spamassassin-prefork.patch
deleted file mode 100644 (file)
index b308321..0000000
+++ /dev/null
@@ -1,846 +0,0 @@
-Index: MANIFEST
-===================================================================
---- MANIFEST   (revision 103454)
-+++ MANIFEST   (working copy)
-@@ -52,6 +52,8 @@
- lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm
- lib/Mail/SpamAssassin/PluginHandler.pm
- lib/Mail/SpamAssassin/Reporter.pm
-+lib/Mail/SpamAssassin/SpamdForkScaling.pm
-+lib/Mail/SpamAssassin/SubProcBackChannel.pm
- lib/Mail/SpamAssassin/SQLBasedAddrList.pm
- lib/Mail/SpamAssassin/TextCat.pm
- lib/Mail/SpamAssassin/Util.pm
-Index: lib/Mail/SpamAssassin/SubProcBackChannel.pm
-===================================================================
---- lib/Mail/SpamAssassin/SubProcBackChannel.pm        (revision 0)
-+++ lib/Mail/SpamAssassin/SubProcBackChannel.pm        (revision 0)
-@@ -0,0 +1,155 @@
-+# back-channel for communication between a master and multiple slave processes.
-+#
-+# <@LICENSE>
-+# Copyright 2004 Apache Software Foundation
-+# 
-+# Licensed under the Apache License, Version 2.0 (the "License");
-+# you may not use this file except in compliance with the License.
-+# You may obtain a copy of the License at
-+# 
-+#     http://www.apache.org/licenses/LICENSE-2.0
-+# 
-+# Unless required by applicable law or agreed to in writing, software
-+# distributed under the License is distributed on an "AS IS" BASIS,
-+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-+# See the License for the specific language governing permissions and
-+# limitations under the License.
-+# </@LICENSE>
-+
-+package Mail::SpamAssassin::SubProcBackChannel;
-+
-+use strict;
-+use warnings;
-+use bytes;
-+
-+use IO::Socket;
-+use Mail::SpamAssassin::Util;
-+use Mail::SpamAssassin::Constants qw(:sa);
-+
-+use vars qw {
-+};
-+
-+my @ISA = qw();
-+
-+=head1 NAME
-+
-+Mail::SpamAssassin::SubProcBackChannel - back-channel for communication between a master and multiple slave processes
-+
-+=head1 METHODS
-+
-+=over 4
-+
-+=cut
-+
-+
-+###########################################################################
-+
-+sub new {
-+  my $class = shift;
-+  $class = ref($class) || $class;
-+
-+  my $self = shift;
-+  if (!defined $self) { $self = { }; }
-+  bless ($self, $class);
-+
-+  $self->{kids} = { };
-+  $self->{fileno_to_fh} = { };
-+
-+  $self;
-+}
-+
-+###########################################################################
-+
-+sub set_selector {
-+  my ($self, $sel) = @_;
-+  $self->{selector} = $sel;
-+}
-+
-+sub setup_backchannel_parent_pre_fork {
-+  my ($self) = @_;
-+
-+  my $io = IO::Socket->new();
-+  ($self->{latest_kid_fh}, $self->{parent}) =
-+            $io->socketpair(AF_UNIX,SOCK_STREAM,PF_UNSPEC)
-+            or die "backchannel: socketpair failed: $!";
-+}
-+
-+sub setup_backchannel_parent_post_fork {
-+  my ($self, $pid) = @_;
-+
-+  my $fh = $self->{latest_kid_fh};
-+
-+  close $self->{parent};    # because it's us!
-+
-+  # disable caching for parent<->child relations
-+  my ($old) = select($fh);
-+  $|++;
-+  select($old);
-+
-+  $self->{kids}->{$pid} = $fh;
-+  $self->add_to_selector($fh);
-+}
-+
-+sub add_to_selector {
-+  my ($self, $fh) = @_;
-+  my $fno = fileno($fh);
-+  $self->{fileno_to_fh}->{$fno} = $fh;
-+  vec (${$self->{selector}}, $fno, 1) = 1;
-+}
-+
-+sub select_vec_to_fh_list {
-+  my ($self, $vec) = @_;
-+  my $i = -1;
-+
-+  # grotesque hackery alert! ;)   turn the vec() map of fds into a list of
-+  # filehandles.  note that filenos that don't have a filehandle in the
-+  # {fileno_to_fh} hash will be ignored; this is by design, so that other fhs
-+  # can be selected on using the same vec, and the caller can just check for
-+  # those in their own code, before they fall back to using this method.
-+
-+  return grep {
-+        defined
-+      } map {
-+        $i++;
-+        ($_ ? $self->{fileno_to_fh}->{$i} : undef);
-+      } split (//, unpack ("b*", $vec));
-+}
-+
-+sub get_socket_for_child {
-+  my ($self, $pid) = @_;
-+  return $self->{kids}->{$pid};
-+}
-+
-+###########################################################################
-+
-+sub setup_backchannel_child_post_fork {
-+  my ($self) = @_;
-+
-+  close $self->{latest_kid_fh}; # because it's us!
-+
-+  my $old = select($self->{parent});
-+  $| = 1;   # print to parent by default, turn off buffering
-+  select($old);
-+}
-+
-+sub get_parent_socket {
-+  my ($self) = @_;
-+  return $self->{parent};
-+}
-+
-+############################################################################
-+
-+1;
-+
-+__END__
-+
-+=back
-+
-+=head1 SEE ALSO
-+
-+C<Mail::SpamAssassin>
-+C<Mail::SpamAssassin::ArchiveIterator>
-+C<Mail::SpamAssassin::SpamdPreforkScaling>
-+C<spamassassin>
-+C<spamd>
-+C<mass-check>
-Index: lib/Mail/SpamAssassin/SpamdForkScaling.pm
-===================================================================
---- lib/Mail/SpamAssassin/SpamdForkScaling.pm  (revision 0)
-+++ lib/Mail/SpamAssassin/SpamdForkScaling.pm  (revision 0)
-@@ -0,0 +1,383 @@
-+# spamd prefork scaling, using an Apache-based algorithm
-+#
-+# <@LICENSE>
-+# Copyright 2004 Apache Software Foundation
-+# 
-+# Licensed under the Apache License, Version 2.0 (the "License");
-+# you may not use this file except in compliance with the License.
-+# You may obtain a copy of the License at
-+# 
-+#     http://www.apache.org/licenses/LICENSE-2.0
-+# 
-+# Unless required by applicable law or agreed to in writing, software
-+# distributed under the License is distributed on an "AS IS" BASIS,
-+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-+# See the License for the specific language governing permissions and
-+# limitations under the License.
-+# </@LICENSE>
-+
-+package Mail::SpamAssassin::SpamdForkScaling;
-+
-+*dbg=\&Mail::SpamAssassin::dbg;
-+
-+use strict;
-+use warnings;
-+use bytes;
-+
-+use Mail::SpamAssassin::Util;
-+
-+use vars qw {
-+  @PFSTATE_VARS %EXPORT_TAGS @EXPORT_OK
-+};
-+
-+use base qw( Exporter );
-+
-+@PFSTATE_VARS = qw(
-+  PFSTATE_ERROR PFSTATE_STARTING PFSTATE_IDLE PFSTATE_BUSY PFSTATE_KILLED
-+  PFORDER_ACCEPT
-+);
-+
-+%EXPORT_TAGS = (
-+  'pfstates' => [ @PFSTATE_VARS ]
-+);
-+@EXPORT_OK = ( @PFSTATE_VARS );
-+
-+use constant PFSTATE_ERROR       => -1;
-+use constant PFSTATE_STARTING    => 0;
-+use constant PFSTATE_IDLE        => 1;
-+use constant PFSTATE_BUSY        => 2;
-+use constant PFSTATE_KILLED      => 3;
-+
-+use constant PFORDER_ACCEPT      => 10;
-+
-+###########################################################################
-+
-+sub new {
-+  my $class = shift;
-+  $class = ref($class) || $class;
-+
-+  my $self = shift;
-+  if (!defined $self) { $self = { }; }
-+  bless ($self, $class);
-+
-+  $self->{kids} = { };
-+  $self->{overloaded} = 0;
-+  $self->{min_children} ||= 1;
-+
-+  $self;
-+}
-+
-+###########################################################################
-+# Parent methods
-+
-+sub add_child {
-+  my ($self, $pid) = @_;
-+  $self->set_child_state ($pid, PFSTATE_STARTING);
-+}
-+
-+sub child_exited {
-+  my ($self, $pid) = @_;
-+  delete $self->{kids}->{$pid};
-+}
-+
-+sub set_child_state {
-+  my ($self, $pid, $state) = @_;
-+  $self->{kids}->{$pid} = $state;
-+  dbg ("prefork: child $pid: entering state $state");
-+  $self->compute_lowest_child_pid();
-+}
-+
-+sub compute_lowest_child_pid {
-+  my ($self) = @_;
-+
-+  my @pids = grep { $self->{kids}->{$_} == PFSTATE_IDLE }
-+        keys %{$self->{kids}};
-+
-+  my $l = shift @pids;
-+  foreach my $p (@pids) {
-+    if ($l > $p) { $l = $p };
-+  }
-+  $self->{lowest_idle_pid} = $l;
-+}
-+
-+###########################################################################
-+
-+sub set_server_fh {
-+  my ($self, $fh) = @_;
-+  $self->{server_fh} = $fh;
-+  $self->{server_fileno} = $fh->fileno();
-+}
-+
-+sub main_server_poll {
-+  my ($self, $tout) = @_;
-+
-+  my $rin = ${$self->{backchannel}->{selector}};
-+  if ($self->{overloaded}) {
-+    # don't select on the server fh -- we already KNOW that's ready,
-+    # since we're overloaded
-+    vec($rin, $self->{server_fileno}, 1) = 0;
-+  }
-+
-+  my ($rout, $eout);
-+  my ($nfound, $timeleft) = select($rout=$rin, undef, $eout=$rin, $tout);
-+
-+  # any action?
-+  return unless ($nfound);
-+
-+  # were the kids ready, or did we get signal?
-+  if (vec ($rout, $self->{server_fileno}, 1)) {
-+    # dbg("prefork: server fh ready");
-+    # the server socket: new connection from a client
-+    if (!$self->order_idle_child_to_accept()) {
-+      # dbg("prefork: no idle kids, noting overloaded");
-+      # there are no idle kids!  we're overloaded, mark that
-+      $self->{overloaded}++;
-+    }
-+    return;
-+  }
-+
-+  foreach my $fh ($self->{backchannel}->select_vec_to_fh_list($rout))
-+  {
-+    # otherwise it's a status report from a child.
-+    # just read one line.  if there's more lines, we'll get them
-+    # when we re-enter the can_read() select call above...
-+    if ($self->read_one_line_from_child_socket($fh) == PFSTATE_IDLE)
-+    {
-+      dbg("prefork: child reports idle");
-+      if ($self->{overloaded}) {
-+        # if we were overloaded, then now that this kid is idle,
-+        # we can use it to handle the waiting connection.  zero
-+        # the overloaded flag, anyway; if there's >1 waiting
-+        # conn, they'll show up next time we do the select.
-+
-+        dbg("prefork: overloaded, immediately telling kid to accept");
-+        if (!$self->order_idle_child_to_accept()) {
-+          # this should not happen
-+          warn "prefork: oops! still overloaded?";
-+        }
-+        dbg("prefork: no longer overloaded");
-+        $self->{overloaded} = 0;
-+      }
-+    }
-+  }
-+
-+  # now that we've ordered some kids to accept any new connections,
-+  # increase/decrease the pool as necessary
-+  $self->adapt_num_children();
-+}
-+
-+sub read_one_line_from_child_socket {
-+  my ($self, $sock) = @_;
-+
-+  my $line = $sock->getline();
-+  if (!defined $line) {
-+    dbg ("prefork: child closed connection");
-+
-+    # stop it being select'd
-+    vec(${$self->{backchannel}->{selector}}, $sock->fileno, 1) = 0;
-+    $sock->close();
-+    return PFSTATE_ERROR;
-+  }
-+
-+  chomp $line;
-+  if ($line =~ /^I(\d+)/) {
-+    $self->set_child_state ($1, PFSTATE_IDLE);
-+    return PFSTATE_IDLE;
-+  }
-+  elsif ($line =~ /^B(\d+)/) {
-+    $self->set_child_state ($1, PFSTATE_BUSY);
-+    return PFSTATE_BUSY;
-+  }
-+  else {
-+    die "unknown message from child: '$line'";
-+    return PFSTATE_ERROR;
-+  }
-+}
-+
-+###########################################################################
-+
-+# we use the following protocol between the master and child processes to
-+# control when they accept/who accepts: server tells a child to accept with a
-+# "A\n", child responds with "B$pid\n" when it's busy, and "I$pid\n" once it's
-+# idle again.  Very simple, line-based protocol.
-+
-+sub order_idle_child_to_accept {
-+  my ($self) = @_;
-+
-+  my $kid = $self->{lowest_idle_pid};
-+  if (defined $kid) {
-+    my $sock = $self->{backchannel}->get_socket_for_child($kid);
-+    $sock->syswrite ("A\n");
-+    dbg ("prefork: ordered $kid to accept");
-+
-+    # now wait for it to say it's done that
-+    return $self->wait_for_child_to_accept($sock);
-+
-+  }
-+  else {
-+    dbg ("prefork: no spare children to accept, waiting for one to complete");
-+    return undef;
-+  }
-+}
-+
-+sub wait_for_child_to_accept {
-+  my ($self, $sock) = @_;
-+
-+  while (1) {
-+    my $state = $self->read_one_line_from_child_socket($sock);
-+    if ($state == PFSTATE_BUSY) {
-+      return 1;     # 1 == success
-+    }
-+    if ($state == PFSTATE_ERROR) {
-+      return undef;
-+    }
-+    else {
-+      die "prefork: ordered child to accept, but child reported state '$state'";
-+    }
-+  }
-+}
-+
-+sub child_now_ready_to_accept {
-+  my ($self, $kid) = @_;
-+  if ($self->{waiting_for_idle_child}) {
-+    my $sock = $self->{backchannel}->get_socket_for_child($kid);
-+    $sock->syswrite ("A\n");
-+    $self->{waiting_for_idle_child} = 0;
-+  }
-+}
-+
-+###########################################################################
-+# Child methods
-+
-+sub set_my_pid {
-+  my ($self, $pid) = @_;
-+  $self->{pid} = $pid;  # save calling $$ all the time
-+}
-+
-+sub update_child_status_idle {
-+  my ($self) = @_;
-+  $self->report_backchannel_socket("I".$self->{pid}."\n");
-+}
-+
-+sub update_child_status_busy {
-+  my ($self) = @_;
-+  $self->report_backchannel_socket("B".$self->{pid}."\n");
-+}
-+
-+sub report_backchannel_socket {
-+  my ($self, $str) = @_;
-+  my $sock = $self->{backchannel}->get_parent_socket();
-+  syswrite ($sock, $str)
-+        or write "syswrite() to parent failed: $!";
-+}
-+
-+sub wait_for_orders {
-+  my ($self) = @_;
-+
-+  my $sock = $self->{backchannel}->get_parent_socket();
-+  while (1) {
-+    my $line = $sock->getline();
-+    chomp $line if defined $line;
-+    if (index ($line, "A") == 0) {  # string starts with "A" = accept
-+      return PFORDER_ACCEPT;
-+    }
-+    else {
-+      die "unknown order from parent: '$line'";
-+      return undef;
-+    }
-+  }
-+}
-+
-+###########################################################################
-+# Master server code again
-+
-+# this is pretty much the algorithm from perform_idle_server_maintainance() in
-+# Apache's "prefork" MPM.  However: we don't do exponential server spawning,
-+# since our servers are a lot more heavyweight than theirs is.
-+
-+sub adapt_num_children {
-+  my ($self) = @_;
-+
-+  my $kids = $self->{kids};
-+  my $statestr = '';
-+  my $num_idle = 0;
-+  my @pids = sort { $a <=> $b } keys %{$kids};
-+  my $num_servers = scalar @pids;
-+
-+  foreach my $pid (@pids) {
-+    my $k = $kids->{$pid};
-+    if ($k == PFSTATE_IDLE) {
-+      $statestr .= 'I';
-+      $num_idle++;
-+    }
-+    elsif ($k == PFSTATE_BUSY) {
-+      $statestr .= 'B';
-+    }
-+    elsif ($k == PFSTATE_KILLED) {
-+      $statestr .= 'K';
-+    }
-+    elsif ($k == PFSTATE_ERROR) {
-+      $statestr .= 'E';
-+    }
-+    elsif ($k == PFSTATE_STARTING) {
-+      $statestr .= 'S';
-+    }
-+    else {
-+      $statestr .= '?';
-+    }
-+  }
-+  dbg ("prefork: child states: ".$statestr);
-+
-+  # just kill off/add one at a time, to avoid swamping stuff and
-+  # reacting too quickly; Apache emulation
-+  if ($num_idle < $self->{min_idle}) {
-+    if ($num_servers < $self->{max_children}) {
-+      $self->need_to_add_server($num_idle);
-+    } else {
-+      warn "prefork: server reached --max-clients setting, consider raising it\n";
-+    }
-+  }
-+  elsif ($num_idle > $self->{max_idle} && $num_servers > $self->{min_children}) {
-+    $self->need_to_del_server($num_idle);
-+  }
-+}
-+
-+sub need_to_add_server {
-+  my ($self, $num_idle) = @_;
-+  my $cur = ${$self->{cur_children_ref}};
-+  $cur++;
-+  dbg ("prefork: adjust: increasing, not enough idle children ($num_idle < $self->{min_idle})");
-+  main::spawn();
-+  # servers will be started once main_server_poll() returns
-+}
-+
-+sub need_to_del_server {
-+  my ($self, $num_idle) = @_;
-+  my $cur = ${$self->{cur_children_ref}};
-+  $cur--;
-+  my $pid;
-+  foreach my $k (keys %{$self->{kids}}) {
-+    my $v = $self->{kids}->{$k};
-+    if ($v == PFSTATE_IDLE)
-+    {
-+      # kill the highest; Apache emulation, exploits linux scheduler
-+      # behaviour (and is predictable)
-+      if (!defined $pid || $k > $pid) {
-+        $pid = $k;
-+      }
-+    }
-+  }
-+
-+  if (!defined $pid) {
-+    # this should be impossible. assert it
-+    die "oops! no idle kids in need_to_del_server?";
-+  }
-+
-+  kill 'INT' => $pid;
-+  $self->set_child_state ($pid, PFSTATE_KILLED);
-+  dbg ("prefork: adjust: decreasing, too many idle children ($num_idle > $self->{max_idle}), killed $pid");
-+}
-+
-+1;
-+
-+__END__
-Index: spamd/spamd.raw
-===================================================================
---- spamd/spamd.raw    (revision 103454)
-+++ spamd/spamd.raw    (working copy)
-@@ -39,6 +39,8 @@
- use Mail::SpamAssassin;
- use Mail::SpamAssassin::NetSet;
-+use Mail::SpamAssassin::SubProcBackChannel;
-+use Mail::SpamAssassin::SpamdForkScaling qw(:pfstates);
- use Getopt::Long;
- use Pod::Usage;
-@@ -82,7 +84,9 @@
-   EX_CONFIG      => 78,    # configuration error
- );
-+*dbg = \&Mail::SpamAssassin::dbg;
-+
- sub print_version {
-   printf("%s version %s\n", "SpamAssassin Server", Mail::SpamAssassin::Version());
-   printf("  running on Perl %s\n", join(".", map { $_*1 } ($] =~ /(\d)\.(\d{3})(\d{3})/)));
-@@ -109,8 +113,14 @@
- my %opt = (
-   'user-config'   => 1,
-   'ident-timeout' => 5.0,
-+  # scaling settings; some of these aren't actually settable via cmdline
-+  'server-scale-period' => 2,   # how often to scale the # of kids, secs
-+  'min-children'  => 1,         # min kids to have running
-+  'min-spare'     => 1,         # min kids that must be spare
-+  'max-spare'     => 2,         # max kids that should be spare
- );
-+
- # Untaint all command-line options and ENV vars, since spamd is launched
- # as a daemon from a known-safe environment. Also store away some of the
- # vars we need for a SIGHUP later on.
-@@ -153,7 +163,11 @@
-   'listen-ip|ip-address|i:s' => \$opt{'listen-ip'},
-   'local!'                   => \$opt{'local'},
-   'L'                        => \$opt{'local'},
-+  'round-robin!'             => \$opt{'round-robin'},
-+  'min-children=i'           => \$opt{'min-children'},
-   'max-children|m=i'         => \$opt{'max-children'},
-+  'min-spare=i'              => \$opt{'min-spare'},
-+  'max-spare=i'              => \$opt{'max-spare'},
-   'max-conn-per-child=i'     => \$opt{'max-conn-per-child'},
-   'nouser-config|x'          => sub { $opt{'user-config'} = 0 },
-   'paranoid!'                => \$opt{'paranoid'},
-@@ -515,7 +529,23 @@
- $childlimit        ||= 5;
- $clients_per_child ||= 200;
-+# ensure scaling parameters are logical
-+if ($opt{'min-children'} < 1) {
-+  $opt{'min-children'} = 1;
-+}
-+if ($opt{'min-spare'} < 0) {
-+  $opt{'min-spare'} = 0;
-+}
-+if ($opt{'min-spare'} > $childlimit) {
-+  $opt{'min-spare'} = $childlimit-1;
-+}
-+if ($opt{'max-spare'} < $opt{'min-spare'}) {
-+  # emulate Apache behaviour:
-+  # http://httpd.apache.org/docs-2.0/mod/prefork.html#maxspareservers
-+  $opt{'max-spare'} = $opt{'min-spare'}+1;
-+}
-+
- my $dontcopy = 1;
- if ( $opt{'create-prefs'} ) { $dontcopy = 0; }
-@@ -571,6 +601,29 @@
-   $listeninfo = "port $port/tcp";
- }
-+my $backchannel = Mail::SpamAssassin::SubProcBackChannel->new();
-+my $scaling;
-+if (!$opt{'round-robin'})
-+{
-+  my $max_children = $childlimit;
-+
-+  # change $childlimit to avoid churn when we startup and create loads
-+  # of spare servers; when we're using scaling, it's not as important
-+  # as it was with the old algorithm.
-+  if ($childlimit > $opt{'max-spare'}) {
-+    $childlimit = $opt{'max-spare'};
-+  }
-+
-+  $scaling = Mail::SpamAssassin::SpamdForkScaling->new({
-+        backchannel => $backchannel,
-+        min_children => $opt{'min-children'},
-+        max_children => $max_children,
-+        min_idle => $opt{'min-spare'},
-+        max_idle => $opt{'max-spare'},
-+        cur_children_ref => \$childlimit
-+      });
-+}
-+
- # Be a well-behaved daemon
- my $server;
- if ( $opt{'socketpath'} ) {
-@@ -747,6 +800,10 @@
- my $got_sighup;
- setup_parent_sig_handlers();
-+my $select_mask = '';
-+vec($select_mask, $server->fileno, 1) = 1;
-+$backchannel->set_selector(\$select_mask);
-+
- # log server started, but processes watching the log to wait for connect
- # should wait until they see the pid, after signal handlers are in place
- if ( defined $opt{'debug'} ) {
-@@ -781,8 +838,16 @@
-   warn "server pid: $$\n";
- }
-+if ($scaling) {
-+  $scaling->set_server_fh($server);
-+}
-+
- while (1) {
--  sleep;    # wait for a signal (ie: child's death)
-+  if (!$scaling) {
-+    sleep;    # wait for a signal (ie: child's death)
-+  } else {
-+    $scaling->main_server_poll($opt{'server-scale-period'});
-+  }
-   if ( defined $got_sighup ) {
-     if (defined($opt{'pidfile'})) {
-@@ -803,7 +868,7 @@
-       . ": $!\n";
-   }
--  for ( my $i = keys %children ; $i < $childlimit ; $i++ ) {
-+  for (my $i = keys %children; $i < $childlimit; $i++) {
-     spawn();
-   }
- }
-@@ -812,6 +877,8 @@
- sub spawn {
-   my $pid;
-+  $backchannel->setup_backchannel_parent_pre_fork();
-+
-   # block signal for fork
-   my $sigset = POSIX::SigSet->new( POSIX::SIGINT() );
-   sigprocmask( POSIX::SIG_BLOCK(), $sigset )
-@@ -826,6 +893,10 @@
-       or die "Can't unblock SIGINT for fork: $!\n";
-     $children{$pid} = 1;
-     logmsg("server successfully spawned child process, pid $pid");
-+    $backchannel->setup_backchannel_parent_post_fork($pid);
-+    if ($scaling) {
-+      $scaling->add_child($pid);
-+    }
-     return;
-   }
-   else {
-@@ -864,9 +935,23 @@
-     # this will help make it clear via process listing which is child/parent
-     $0 = 'spamd child';
-+    $backchannel->setup_backchannel_child_post_fork();
-+    if ($scaling) {     # only do this once, for efficiency; $$ is a syscall
-+      $scaling->set_my_pid($$);
-+    }
-+
-     # handle $clients_per_child connections, then die in "old" age...
-+    my $orders;
-     for ( my $i = 0 ; $i < $clients_per_child ; $i++ ) {
-+      if ($scaling) {
-+        $scaling->update_child_status_idle();
-+        $orders = $scaling->wait_for_orders(); # and sleep...
-+        if ($orders != PFORDER_ACCEPT) {
-+          logmsg ("unknown order: $orders");
-+        }
-+      }
-+
-       # use a large eval scope to catch die()s and ensure they
-       # don't kill the server.
-       my $evalret = eval { accept_a_conn(); };
-@@ -934,6 +1019,10 @@
-   $client->autoflush(1);
-+  if ($scaling) {
-+    $scaling->update_child_status_busy();
-+  }
-+
-   # keep track of start time
-   my $start = time;
-@@ -1503,7 +1592,7 @@
- sub handle_user_ldap {
-   my $username = shift;
--  Mail::SpamAssassin::dbg("handle_user_ldap($username)");
-+  dbg("handle_user_ldap($username)");
-   $spamtest->load_scoreonly_ldap($username);
-   $spamtest->signal_user_changed(
-     {
-@@ -1626,6 +1715,7 @@
-   $SIG{CHLD} = \&child_handler;
-   $SIG{INT}  = \&kill_handler;
-   $SIG{TERM} = \&kill_handler;
-+  $SIG{PIPE} = 'IGNORE';
- }
- # sig handlers: child processes
-@@ -1775,6 +1865,10 @@
-     # remove them from our child listing
-     delete $children{$pid};
-+    if ($scaling) {
-+      $scaling->child_exited($pid);
-+    }
-+
-     unless ($main::INHIBIT_LOGGING_IN_SIGCHLD_HANDLER) {
-       logmsg("handled cleanup of child pid $pid");
-     }
-@@ -1919,8 +2013,12 @@
-  -i [ipaddr], --listen-ip=ipaddr    Listen on the IP ipaddr
-  -p port, --port                    Listen on specified port
-  -m num, --max-children=num         Allow maximum num children
-+ --min-children=num                 Allow minimum num children
-+ --min-spare=num                    Lower limit for number of spare children
-+ --max-spare=num                    Upper limit for number of spare children
-  --max-conn-per-child=num         Maximum connections accepted by child 
-                                     before it is respawned
-+ --round-robin                      Use traditional prefork algorithm
-  -q, --sql-config                   Enable SQL config (only useful with -x)
-  -Q, --setuid-with-sql              Enable SQL config (only useful with -x,
-                                     enables use of -H)
-@@ -2236,12 +2334,46 @@
- Please note that there is a OS specific maximum of connections that can be
- queued (Try C<perl -MSocket -e'print SOMAXCONN'> to find this maximum).
-+Note that if you run too many servers for the amount of free RAM available, you
-+run the danger of hurting performance by causing a high swap load as server
-+processes are swapped in and out continually.
-+
-+=item B<--min-children>=I<number>
-+
-+The minimum number of children that will be kept running.  The minimum value is
-+C<1>, the default value is C<1>.  If you have lots of free RAM, you may want to
-+increase this.
-+
-+=item B<--min-spare>=I<number>
-+
-+The lower limit for the number of spare children allowed to run.  A
-+spare, or idle, child is one that is not handling a scan request.   If
-+there are too few spare children available, a new server will be started
-+every second or so.  The default value is C<1>.
-+
-+=item B<--max-spare>=I<number>
-+
-+The upper limit for the number of spare children allowed to run.  If there
-+are too many spare children, one will be killed every second or so until
-+the number of idle children is in the desired range.  The default value
-+is C<2>.
-+
- =item B<--max-conn-per-child>=I<number>
- This option specifies the maximum number of connections each child
- should process before dying and letting the master spamd process spawn
- a new child.  The minimum value is C<1>, the default value is C<200>.
-+=item B<--round-robin>
-+
-+By default, C<spamd> will attempt to keep a small number of "hot" child
-+processes as busy as possible, and keep any others as idle as possible, using
-+something similar to the Apache httpd server scaling algorithm.  This is
-+accomplished by the master process coordinating the activities of the children.
-+This switch will disable this scaling algorithm, and the behaviour seen in
-+versions 3.0.0 and 3.0.1 will be used instead, where all processes receive an
-+equal load and no scaling takes place.
-+
- =item B<-H> I<directory>, B<--helper-home-dir>=I<directory>
- Specify that external programs such as Razor, DCC, and Pyzor should have
This page took 0.167943 seconds and 4 git commands to generate.