This patch makes sure that hook_disconnect and hook_reset_transaction
plugins are run at the end of all transactions, including those where
the remote end hung up unexpectedly or we timed out the connection.

My previous changes were a bit more complex than they had to be, had no
effect on apache or async, and further testing indicated that they did
not affect timed out connections.  This patch is tested to work for both
hang-ups and timeouts from prefork, and should work for the rest of the
server modes -- EXCEPT that I couldn't figure out where to modify
timeout behavior for the apache mode.  Does anyone have any ideas on that
one?
---
 lib/Apache/Qpsmtpd.pm            |    1 +
 lib/Qpsmtpd.pm                   |    8 ++++++++
 lib/Qpsmtpd/PollServer.pm        |    1 +
 lib/Qpsmtpd/SMTP.pm              |    6 +-----
 lib/Qpsmtpd/TcpServer.pm         |    1 +
 lib/Qpsmtpd/TcpServer/Prefork.pm |    1 +
 6 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/lib/Apache/Qpsmtpd.pm b/lib/Apache/Qpsmtpd.pm
index 0433324..b3ca5b6 100644
--- a/lib/Apache/Qpsmtpd.pm
+++ b/lib/Apache/Qpsmtpd.pm
@@ -127,6 +127,7 @@ sub read_input {
             or $self->respond(502, "command unrecognized: '$data'");
         last if $self->{_quitting};
     }
+    $self>disconnect;
 }
 
 sub respond {
diff --git a/lib/Qpsmtpd.pm b/lib/Qpsmtpd.pm
index 6c8d075..4d8c333 100644
--- a/lib/Qpsmtpd.pm
+++ b/lib/Qpsmtpd.pm
@@ -600,6 +600,14 @@ sub auth_mechanism {
   return (defined $self->{_auth_mechanism} ? $self->{_auth_mechanism} : "" );
 }
 
+sub disconnect { 
+  my $self = shift;
+  return if $self->connection->notes('disconnected'); # We only disconnect once
+  $self->run_hooks("disconnect");
+  $self->reset_transaction;
+  $self->connection->notes(disconnected => 1);
+}
+
 1;
 
 __END__
diff --git a/lib/Qpsmtpd/PollServer.pm b/lib/Qpsmtpd/PollServer.pm
index 9d91af7..854dee8 100644
--- a/lib/Qpsmtpd/PollServer.pm
+++ b/lib/Qpsmtpd/PollServer.pm
@@ -164,6 +164,7 @@ sub disconnect {
 
 sub close {
     my Qpsmtpd::PollServer $self = shift;
+    $self->disconnect;
     $self->run_hooks_no_respond("post-connection");
     $self->connection->reset;
     $self->SUPER::close;
diff --git a/lib/Qpsmtpd/SMTP.pm b/lib/Qpsmtpd/SMTP.pm
index a820a12..258282c 100644
--- a/lib/Qpsmtpd/SMTP.pm
+++ b/lib/Qpsmtpd/SMTP.pm
@@ -575,11 +575,7 @@ sub quit_respond {
   $self->disconnect();
 }
 
-sub disconnect {
-  my $self = shift;
-  $self->run_hooks("disconnect");
-  $self->reset_transaction;
-}
+sub disconnect { shift->SUPER::disconnect(@_) }
 
 sub data {
   my $self = shift;
diff --git a/lib/Qpsmtpd/TcpServer.pm b/lib/Qpsmtpd/TcpServer.pm
index df9da9a..cdcb77c 100644
--- a/lib/Qpsmtpd/TcpServer.pm
+++ b/lib/Qpsmtpd/TcpServer.pm
@@ -100,6 +100,7 @@ sub read_input {
     alarm $timeout;
   }
   alarm(0);
+  $self->disconnect;
 }
 
 sub respond {
diff --git a/lib/Qpsmtpd/TcpServer/Prefork.pm b/lib/Qpsmtpd/TcpServer/Prefork.pm
index 28f60dc..9c37fac 100644
--- a/lib/Qpsmtpd/TcpServer/Prefork.pm
+++ b/lib/Qpsmtpd/TcpServer/Prefork.pm
@@ -35,6 +35,7 @@ sub read_input {
         or $self->respond(502, "command unrecognized: '$_'");
       alarm $timeout;
     }
+    $self->disconnect;
   };
   if ($@ =~ /^disconnect_tcpserver/) {
        die "disconnect_tcpserver";
-- 
1.5.6.3

Reply via email to