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);