Jan,

> I can understand now where the problem is, but don't see an easy solution
> yet. It should work as it is if you remove the --round-robin option.
> Please open a problem report on the bugzilla.

Please try the attached patch.

It adds some debugging, and handles the --round-robin case
by turning off the inappropriate 0.1 second timeout on a select.

The patch updates spamd/spamd.raw, but should be applicable
(with some offset fuzz) to the installed spamd file too,
with no changes.

  Mark
--- spamd/spamd.raw	(revision 1562510)
+++ spamd/spamd.raw	(working copy)
@@ -1345,7 +1345,7 @@
 
       # use a large eval scope to catch die()s and ensure they
       # don't kill the server.
-      my $evalret = eval { accept_a_conn(); };
+      my $evalret = eval { accept_a_conn($scaling ? 0.5 : undef); };
 
       if (!defined ($evalret)) {
         warn("spamd: error: $@ $!, continuing");
@@ -1408,6 +1408,7 @@
 }
 
 sub accept_from_any_server_socket {
+  my($timeout) = @_;
   my($client, $selected_socket_info);
 
   if (!@listen_sockets) {
@@ -1424,10 +1425,19 @@
     # with a client waiting.
     # (TODO: we could extend the prefork protocol to pass this data)
 
+    my $sel_mask_str = unpack('b*', $server_select_mask);
+    dbg("spamd: select() on fd mask %s, %s",
+        $sel_mask_str, defined $timeout ? "timeout $timeout" : "no timeout");
+
     my $fdvec = $server_select_mask;
-    my $nfound = select($fdvec, undef, undef, 0.1);
-    die "oops? accept_a_conn: no fds ready"  if !$nfound;
+    my $nfound = select($fdvec, undef, undef, $timeout);
 
+    if (!defined $nfound || $nfound < 0) {
+      die "select failed on fd mask $sel_mask_str: $!";
+    } elsif (!$nfound) {
+      die "accept_a_conn: no fd ready, fd mask $sel_mask_str";
+    }
+
     for my $socket_info (@listen_sockets) {
       my $fd = $socket_info->{fd};
       if (defined($fd) && vec($fdvec,$fd,1)) {
@@ -1436,7 +1446,7 @@
       }
     }
     $selected_socket_info
-      or die "accept_a_conn: no fds ready by vec: $fdvec";
+      or die "accept_a_conn: no fds matching a fd vec ".unpack('b*',$fdvec);
   }
 
   if ($selected_socket_info) {
@@ -1452,10 +1462,11 @@
 }
 
 sub accept_a_conn {
+  my ($timeout) = @_;
 
   my $socket_info;
   # $client is a global variable
-  ($client, $socket_info) = accept_from_any_server_socket();
+  ($client, $socket_info) = accept_from_any_server_socket($timeout);
 
   if ($scaling) {
     $scaling->update_child_status_busy();
@@ -1494,9 +1505,9 @@
       peer_info_from_socket($client);
     $remote_hostaddr or die 'failed to obtain port and ip from socket';
 
-    my $msg = sprintf("connection from %s [%s]:%s to port %d",
+    my $msg = sprintf("connection from %s [%s]:%s to port %d, fd %d",
                       $remote_hostname, $remote_hostaddr, $remote_port,
-                      $local_port);
+                      $local_port, $socket_info->{fd});
     if (ip_is_allowed($remote_hostaddr)) {
       info("spamd: $msg");
     }
@@ -3017,6 +3028,7 @@
     my $fd = $socket_info->{fd};
     vec($server_select_mask, $fd, 1) = 1  if defined $fd;
   }
+  dbg("spamd: server sockets fd mask: %s", unpack('b*', $server_select_mask));
 
   my $back_selector = $server_select_mask;
   $backchannel->set_selector(\$back_selector);

Reply via email to