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