Subject: | PATCH - Avoid deadlocks during shutdown |
In some cases we have observed a race condition where PostgreSQL
still has connections open, and waits for them to finish before exiting..
However because Test::postgresql is waiting for Pg to die, the test never
gets to close the connection..
This patch alters things so that it only waits for a few seconds for Pg
to die, before SIGKILLing it, then just waiting a little longer, before
giving up and exiting anyway.
Source is available at: http://gh/tobyc/Test-postgresql/tree/die_harder
Patch against version 0.09 is attached.
Subject: | 0001-Avoid-deadlocks-during-shutdown-by-SIGKILLing-Pg.patch |
From a7dc8aefbb2900c5d3097875f8c172d65d33bcba Mon Sep 17 00:00:00 2001
From: Toby Corkindale <tobyc@strategicdata.com.au>
Date: Fri, 9 Sep 2011 17:14:41 +1000
Subject: [PATCH] Avoid deadlocks during shutdown by SIGKILLing Pg
In some cases we have observed a race condition where PostgreSQL
still has connections open, and waits for them to finish before exiting..
However because Test::postgresql is waiting for Pg to die, the test
never gets to close the connection..
This commit only waits for a few seconds for Pg to die, before SIGKILLing
it, then just waiting a little longer, before giving up and exiting anyway.
---
Changes | 3 +++
Makefile.PL | 1 +
lib/Test/postgresql.pm | 29 ++++++++++++++++++++++++-----
3 files changed, 28 insertions(+), 5 deletions(-)
diff --git a/Changes b/Changes
index 129e4dc..68686ef 100644
--- a/Changes
+++ b/Changes
@@ -1,5 +1,8 @@
Revision history for Perl extension Test::postgresql.
+0.10 xxxxxxxxxxxxxxxxxxxxxxx
+ - Avoid deadlocks during Postgres shutdown.
+
0.09 Fri Oct 23 16:50:00 2009
- change cwd and directory permissions, modes for better testing
diff --git a/Makefile.PL b/Makefile.PL
index 54a8141..d9a3d84 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -5,6 +5,7 @@ name 'Test-postgresql';
all_from 'lib/Test/postgresql.pm';
requires 'Class::Accessor::Lite';
+requires 'Time::HiRes';
test_requires 'DBI';
test_requires 'DBD::Pg';
test_requires 'Test::SharedFork' => 0.06;
diff --git a/lib/Test/postgresql.pm b/lib/Test/postgresql.pm
index f97e8cb..43c0dbb 100644
--- a/lib/Test/postgresql.pm
+++ b/lib/Test/postgresql.pm
@@ -8,9 +8,10 @@ use Class::Accessor::Lite;
use Cwd;
use DBI;
use File::Temp qw(tempdir);
-use POSIX qw(SIGTERM WNOHANG setuid);
+use Time::HiRes qw(nanosleep);
+use POSIX qw(SIGTERM SIGKILL WNOHANG setuid);
-our $VERSION = '0.09';
+our $VERSION = '0.10';
our @SEARCH_PATHS = (
# popular installtion dir?
@@ -85,6 +86,7 @@ sub DESTROY {
my $self = shift;
$self->stop
if defined $self->pid && $$ == $self->_owner_pid;
+ return;
}
sub dsn {
@@ -181,13 +183,30 @@ sub _try_start {
sub stop {
my ($self, $sig) = @_;
- return
- unless defined $self->pid;
+ return unless defined $self->pid;
+
$sig ||= SIGTERM;
+
kill $sig, $self->pid;
- while (waitpid($self->pid, 0) <= 0) {
+ my $timeout = 10 * 1000000000;
+ while ($timeout > 0 and waitpid($self->pid, WNOHANG) <= 0) {
+ $timeout -= nanosleep(500000000);
+ }
+
+ if ($timeout <= 0) {
+ warn "Pg refused to die gracefully; killing it violently.\n";
+ kill SIGKILL, $self->pid;
+ $timeout = 5 * 1000000000;
+ while ($timeout > 0 and waitpid($self->pid, WNOHANG) <= 0) {
+ $timeout -= nanosleep(500000000);
+ }
+ if ($timeout <= 0) {
+ warn "Pg really didn't die.. WTF?\n";
+ }
}
+
$self->pid(undef);
+ return;
}
sub setup {
--
1.7.6