Fix Postgres test hang with DBD::Pg 3.5.0+ (work around RT#100648)
Peter Rabbitson [Thu, 8 Jan 2015 00:42:52 +0000 (01:42 +0100)]
( cherry-pick of 731c2d8b )

It is not 100% clear to me why this is happening, as the change discussed[1]
was not supposed to change behaviour outside of a transaction.

The test in question essentially does a blocking request with a timeout. The
way the default DBIC machinery works is to issue a ping() after the timeout
induced exception, in order to opossibly retry the operation IFF the link
went stale ($dbh thinks everything is in order, the RDBMS believes otherwise).

After the changes in 3.5.0 this ping() now hangs, even though the access
pattern did not change (there are no transactions involved on the handle in
question). Either way, the fix is simple: just shim-away the ping for the
duration of the test.

In general this should be resolved on a higher level by disabling retries for
the duration of the test (or maybe even disabling retries by default in the
distant feature - see RT#47005)

[1] https://rt.cpan.org/Ticket/Display.html?id=100648#txn-1438093

Changes
lib/DBIx/Class/Optional/Dependencies.pm
t/72pg.t
xt/optional_deps.t

diff --git a/Changes b/Changes
index d557c39..777b774 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,5 +1,10 @@
 Revision history for DBIx::Class
 
+    * Fixes
+        - Fix hang in t/72pg.t when run against DBD::Pg 3.5.0. The ping()
+          implementation changes due to RT#100648 made an alarm() based
+          timeout lock-prone.
+
 0.08270 2014-01-30 21:54 (PST)
     * Fixes
         - Fix 0.08260 regression in DBD::SQLite bound int handling. Inserted
index 23ffebe..79b56a0 100644 (file)
@@ -454,7 +454,6 @@ my $reqs = {
         ? (
           # when changing this list make sure to adjust xt/optional_deps.t
           %$rdbms_pg,
-          ($^O ne 'MSWin32' ? ('Sys::SigAction' => '0') : ()),
           'DBD::Pg'               => '2.009002',
         ) : ()
     },
index 44b723c..6371775 100644 (file)
--- a/t/72pg.t
+++ b/t/72pg.t
@@ -337,13 +337,6 @@ lives_ok { $cds->update({ year => '2010' }) } 'Update on prefetched rs';
 ## Test SELECT ... FOR UPDATE
 
   SKIP: {
-      if(eval { require Sys::SigAction }) {
-          Sys::SigAction->import( 'set_sig_handler' );
-      }
-      else {
-        skip "Sys::SigAction is not available", 6;
-      }
-
       my ($timed_out, $artist2);
 
       for my $t (
@@ -382,10 +375,23 @@ lives_ok { $cds->update({ year => '2010' }) } 'Update on prefetched rs';
 
           $timed_out = 0;
           eval {
-              my $h = set_sig_handler( 'ALRM', sub { die "DBICTestTimeout" } );
-              alarm(2);
+              # can not use %SIG assignment directly - we need sigaction below
+              # localization to a block still works however
+              local $SIG{ALRM};
+
+              POSIX::sigaction( POSIX::SIGALRM() => POSIX::SigAction->new(
+                sub { die "DBICTestTimeout" },
+              ));
+
               $artist2 = $schema2->resultset('Artist')->find(1);
               $artist2->name('fooey');
+
+              # FIXME - this needs to go away in lieu of a non-retrying runner
+              # ( i.e. after solving RT#47005 )
+              local *DBIx::Class::Storage::DBI::_ping = sub { 1 }, DBIx::Class::_ENV_::OLD_MRO && Class::C3->reinitialize()
+                if DBIx::Class::_Util::modver_gt_or_eq( 'DBD::Pg' => '3.5.0' );
+
+              alarm(1);
               $artist2->update;
               alarm(0);
           };
index 0ae8023..781273c 100644 (file)
@@ -119,7 +119,6 @@ is_deeply(
 is_deeply(
   DBIx::Class::Optional::Dependencies->req_list_for('test_rdbms_pg'),
   {
-    $^O ne 'MSWin32' ? ('Sys::SigAction' => '0') : (),
     'DBD::Pg'        => '2.009002',
   }, 'optional dependencies for testing Postgres with ENV var ok');