Mailing List Archive

svn commit: r491726 - /spamassassin/trunk/spamd/spamd.raw
Author: sidney
Date: Mon Jan 1 16:27:20 2007
New Revision: 491726

URL: http://svn.apache.org/viewvc?view=rev&rev=491726
Log:
bug 5254: allow for syswrite doing partial writes, fixing a problem with using SSL on some platforms

Modified:
spamassassin/trunk/spamd/spamd.raw

Modified: spamassassin/trunk/spamd/spamd.raw
URL: http://svn.apache.org/viewvc/spamassassin/trunk/spamd/spamd.raw?view=diff&rev=491726&r1=491725&r2=491726
==============================================================================
--- spamassassin/trunk/spamd/spamd.raw (original)
+++ spamassassin/trunk/spamd/spamd.raw Mon Jan 1 16:27:20 2007
@@ -1455,24 +1455,24 @@
my $msg_resp_length = length($msg_resp);
if ( $version >= 1.3 ) # Spamc protocol 1.3 means multi hdrs are OK
{
- syswrite( $client, "SPAMD/1.1 $resphash{$resp} $resp\r\n" .
+ syswrite_full_buffer( $client, "SPAMD/1.1 $resphash{$resp} $resp\r\n" .
"Content-length: $msg_resp_length\r\n" . $spamhdr . "\r\n\r\n" .
$msg_resp );
}
elsif (
$version >= 1.2 ) # Spamc protocol 1.2 means it accepts content-length
{
- syswrite( $client, "SPAMD/1.1 $resphash{$resp} $resp\r\n" .
+ syswrite_full_buffer( $client, "SPAMD/1.1 $resphash{$resp} $resp\r\n" .
"Content-length: $msg_resp_length\r\n\r\n" . $msg_resp );
}
else # Earlier than 1.2 didn't accept content-length
{
- syswrite( $client, "SPAMD/1.0 $resphash{$resp} $resp\r\n" . $msg_resp );
+ syswrite_full_buffer( $client, "SPAMD/1.0 $resphash{$resp} $resp\r\n" . $msg_resp );
}
}
else # $method eq 'CHECK' et al
{
- syswrite( $client, "SPAMD/1.1 $resphash{$resp} $resp\r\n" );
+ syswrite_full_buffer( $client, "SPAMD/1.1 $resphash{$resp} $resp\r\n" );

if ( $method eq "CHECK" ) {
syswrite( $client, "$spamhdr\r\n\r\n" );
@@ -1500,12 +1500,12 @@
if ( $version >= 1.3 ) # Spamc protocol > 1.2 means multi hdrs are OK
{
my $msg_resp_length = length($msg_resp);
- syswrite( $client,
+ syswrite_full_buffer( $client,
"Content-length: $msg_resp_length\r\n" .
$spamhdr . "\r\n\r\n" . $msg_resp );
}
else {
- syswrite( $client, $spamhdr . "\r\n\r\n" . $msg_resp );
+ syswrite_full_buffer( $client, $spamhdr . "\r\n\r\n" . $msg_resp );
}
}
}
@@ -2363,6 +2363,41 @@
$err ||= "do something: $!";
warn "spamd: failed to remove $tmphome: could not $err\n";
}
+}
+
+# Keep calling syswrite until the entire buffer is written out
+# Retry if EAGAIN/EWOULDBLOCK or when partial buffer is written
+# Limit the number of retries to keep the execution time bounded
+sub syswrite_full_buffer {
+ my ($sock, $buf, $numretries) = @_;
+ $numretries ||= 10; # default 10 retries
+ my $length = length($buf);
+ my $written = 0;
+ my $try = 0;
+
+ while (($try < $numretries) && ($length > $written)) {
+ my $nbytes = syswrite($sock, $buf, $length - $written, $written);
+ if (!defined $nbytes) {
+ unless ((exists &Errno::EAGAIN && $! == &Errno::EAGAIN)
+ || (exists &Errno::EWOULDBLOCK && $! == &Errno::EWOULDBLOCK))
+ {
+ # an error that wasn't non-blocking I/O-related. that's serious
+ return undef;
+ }
+ # errcode says to try again
+ }
+ else {
+
+ if ($nbytes == 0) {
+ return $written; # return early if no error but nothing was written
+ }
+
+ $written += $nbytes;
+ }
+ $try++;
+ }
+
+ return $written; # it's complete, we can return
}

sub map_server_sockets {