[svn:qpsmtpd] rev 495 - branches/0.31/plugins/queue

[email protected] 11 Jul 2005 16:00:04 -0000
Newsgroups perl.cvs.qpsmtpd
Message-ID <[email protected]>
Author: msergeant
Date: Mon Jul 11 09:00:03 2005
New Revision: 495

Modified:
   branches/0.31/plugins/queue/qmail-queue
Log:
Work around race condition (not fixed, but mostly fixed)


Modified: branches/0.31/plugins/queue/qmail-queue
==============================================================================
--- branches/0.31/plugins/queue/qmail-queue	(original)
+++ branches/0.31/plugins/queue/qmail-queue	Mon Jul 11 09:00:03 2005
@@ -39,12 +39,12 @@ sub hook_queue {
   my ($self, $transaction) = @_;
 
   # these bits inspired by Peter Samuels "qmail-queue wrapper"
-  pipe(MESSAGE_READER, MESSAGE_WRITER) or fault("Could not create message pipe"), exit;
-  pipe(ENVELOPE_READER, ENVELOPE_WRITER) or fault("Could not create envelope pipe"), exit;
+  pipe(MESSAGE_READER, MESSAGE_WRITER) or die("Could not create message pipe");
+  pipe(ENVELOPE_READER, ENVELOPE_WRITER) or die("Could not create envelope pipe");
 
   my $child = fork();
 
-  not defined $child and fault(451, "Could not fork"), exit;
+  not defined $child and die("Could not fork");
 
   if ($child) {
     # Parent
@@ -52,9 +52,13 @@ sub hook_queue {
                 select(ENVELOPE_WRITER); $| = 1;
     select($oldfh);
 
-    close MESSAGE_READER  or fault("close msg reader fault"),exit;
-    close ENVELOPE_READER or fault("close envelope reader fault"), exit;
+    close MESSAGE_READER  or die("close msg reader fault");
+    close ENVELOPE_READER or die("close envelope reader fault");
 
+    # Note - technically there's a race here because if the exec() below
+    # fails and the writes to MESSAGE_WRITER block we get a deadlocked process.
+    # This check to see if(eof(PIPE)) will catch "most" of these problems.
+    die "Message pipe has been closed" if eof(MESSAGE_WRITER);
     $transaction->header->print(\*MESSAGE_WRITER);
     $transaction->body_resetpos;
     while (my $line = $transaction->body_getline) {
@@ -64,6 +68,7 @@ sub hook_queue {
 
     my @rcpt = map { "T" . $_->address } $transaction->recipients;
     my $from = "F".($transaction->sender->address|| "" );
+    die "Envelope pipe has been closed" if eof(ENVELOPE_WRITER);
     print ENVELOPE_WRITER "$from\0", join("\0",@rcpt), "\0\0"
       or return(DECLINED,"Could not print addresses to queue");
     
@@ -104,6 +109,10 @@ sub hook_queue {
 
     my $rc = exec $queue_exec;
 
+    # close the pipe
+    close(MESSAGE_READER);
+    close(MESSAGE_WRITER);
+    
     exit 6; # we'll only get here if the exec fails
   }
 }