disconnect_reset_transaction.diff:

- call hook_disconnect plugins on *any* disconnection, not just ones involving DENY[SOFT]_DISCONNECT and QUIT
- call hook_reset_transaction plugins one last time when we disconnect

We have a somewhat involved method for logging QP transaction information for our database, and we log such information inside transactions, necessitating a single plugin that collects all of the data that we need and writes it to the database when a transaction is deemed to be over. I've previously had to use a somewhat complex set of hooks that each call a logging subroutine which decides for itself whether it's actually time to do anything; this has been messy and error-prone. I found that I could dispense with all this by using hook_reset_transaction -- with the attached patch applied. In current QP, we don't bother doing reset_transaction on disconnection, presumably because we'll be either letting our child exit or resetting it on the beginning of the next transaction anyhow; but it is useful to run reset_transaction one last time so that, for instance, if the connecting client attempted to send to a few recipients and was denied, we'll be able to catch that information before it vanishes. While testing on this issue, I also found that if we decide to disconnect or if the connecting client quits, hook_disconnect is called -- but if the connecting client simply disconnects, hook_disconnect is not called. This patch also makes sure to call hook_disconnect in this case, but uses a connection note to ensure that hook_disconnect is not called more than is needed.

None of this is tested on -async. It looks pretty obvious that the 'reset_transaction on disconnect' piece of this will work fine there, but I can't tell whether -async even suffers from the disconnect issue that forkserver/prefork did, or if so how to apply my changes there.

This may be my final patch for the night :)

-Jared
Index: lib/Qpsmtpd/TcpServer.pm
===================================================================
--- lib/Qpsmtpd/TcpServer.pm	(revision 967)
+++ lib/Qpsmtpd/TcpServer.pm	(working copy)
@@ -100,6 +100,10 @@
     alarm $timeout;
   }
   alarm(0);
+  return if $self->connection->notes('disconnected');
+  $self->reset_transaction;
+  $self->run_hooks('disconnect');
+  $self->connection->notes(disconnected => 1);
 }
 
 sub respond {
Index: lib/Qpsmtpd/SMTP.pm
===================================================================
--- lib/Qpsmtpd/SMTP.pm	(revision 967)
+++ lib/Qpsmtpd/SMTP.pm	(working copy)
@@ -576,6 +576,7 @@
 sub disconnect {
   my $self = shift;
   $self->run_hooks("disconnect");
+  $self->connection->notes(disconnected => 1);
   $self->reset_transaction;
 }
 
Index: lib/Qpsmtpd/TcpServer/Prefork.pm
===================================================================
--- lib/Qpsmtpd/TcpServer/Prefork.pm	(revision 967)
+++ lib/Qpsmtpd/TcpServer/Prefork.pm	(working copy)
@@ -35,6 +35,11 @@
         or $self->respond(502, "command unrecognized: '$_'");
       alarm $timeout;
     }
+    unless ($self->connection->notes('disconnected')) {
+      $self->reset_transaction;
+      $self->run_hooks('disconnect');
+      $self->connection->notes(disconnected => 1);
+    }
   };
   if ($@ =~ /^disconnect_tcpserver/) {
   	die "disconnect_tcpserver";

Reply via email to