Skip Menu |

This queue is for tickets about the DBD-Pg CPAN distribution.

Report information
The Basics
Id: 55755
Status: rejected
Priority: 0/
Queue: DBD-Pg

People
Owner: Nobody in particular
Requestors: fabien.coelho [...] mines-paristech.fr
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



CC: dbd-pg [...] perl.org
Subject: DBD::Pg not thread safe ?
Date: Sun, 21 Mar 2010 10:22:45 +0100 (CET)
To: bug-dbd-pg [...] rt.cpan.org
From: Fabien COELHO <fabien.coelho [...] mines-paristech.fr>
Hello bug-report automaton ! Hello maintainer ! I always run into segmentation faults when running two parallel database connections in distinct threads. It is not new and was always true, it is just that today I decided to write a bug report:-) Version: DBI 1.609, DBD:Pg 2.13.1 Perl: v5.10.0 built for i486-linux-gnu-thread-multi OS: Linux Ubuntu Karmic (9.10) libpq: 8.4.2 With pg_comparator (http://www.coelho.net/pg_comparator) using the -T (thread option). The script creates two threads which perform queries in parallel on two distinct connections. This result in: ... Can't call do method on handle DBI::db=HASH(0xb6c1a238) after take_imp_data() at ./pg_comparator line 789. ... Use of uninitialized value in subroutine entry at ./pg_comparator line 789. Segmentation fault line 789 is : return $dbh->do($query); query is (from the debug output, if I'm not mistaken about the thread) : CREATE TEMPORARY TABLE cmp_2_1 AS SELECT idc & 0 AS idc, xor(cks) AS cks FROM cmp_2_0 GROUP BY idc & 0 Sorry, no time for a "minimal" or even "small" example... However you can find attached a DBI level 10 trace with and without threads. Only the threaded version does a segmentation fault. Repeat: with pg_comparator (http://coelho.net/pg_comparator), load extensions (see INSTALL) and then run on a table in a base by substitutuing login, password, host, base, table, pkey, other, cols according to your setting... Show quoted text
sh> DBI_TRACE=10 pg_comparator -v -v -v -T \
login:password@host/base/table?pkey:other,cols \ login:password@host/base/table?pkey:other,cols ... lots of stuff, see trace... ... segmentation fault Note that it works fine when the -T option is removed, so there is a workaround which is not to use threads. Possibly the issue is in libpq which may not be thread safe under some conditions, but this is not expected. I tested: Show quoted text
sh> cat test.c
#include<stdio.h> #include "libpq-fe.h" int main(void) { fprintf(stdout, "thread safety is %d\n", PQisthreadsafe()); return 0; } Show quoted text
sh> gcc -I/usr/include/postgresql -lpq test.c sh> ./a.out
thread safety is 1 -- Fabien COELHO.

Message body is not shown because sender requested not to inline it.

Message body is not shown because sender requested not to inline it.

Looks like the problem from the log is: Thread 4 terminated abnormally: (null) do failed: handle 15124 is owned by thread b6db3b14 not current thread b6db3620 (handles can't be shared between threads and your driver may need a CLONE method added) at ./pg_comparator line 789. Are you sure your program is getting a fresh $dbh after cloning?
Subject: Re: [rt.cpan.org #55755] DBD::Pg not thread safe ?
Date: Tue, 29 Mar 2011 08:50:06 +0200 (CEST)
To: Greg Sabino Mullane via RT <bug-DBD-Pg [...] rt.cpan.org>
From: Fabien COELHO <fabien.coelho [...] mines-paristech.fr>
Hello, Show quoted text
> <URL: https://rt.cpan.org/Ticket/Display.html?id=55755 > > > Looks like the problem from the log is: > > Thread 4 terminated abnormally: (null) do failed: handle 15124 is owned > by thread b6db3b14 not current thread b6db3620 (handles can't be shared > between threads and your driver may need a CLONE method added) at > ./pg_comparator line 789. > > Are you sure your program is getting a fresh $dbh after cloning?
Hmmm. I use a pool of two connections used by two concurrent threads and I rely on the serialize/unserialize feature to reuse the connection between parallel computations which are performed by successive threads: $dbh->take_imp_data, DBI->connect(driver($db), undef, undef, { 'dbi_imp_data' => $dbh }). I do not know whether this is "fresh" enough. There is indeed a new thread, and the initial one which created the connection is long dead. Note that this works fine with the mysql driver. Maybe the serialization keeps track of its thread handle, where it should not? -- Fabien.
It's not recommended to use DBI objects across threads. Use something like DBIx::Connector to use a single "connection" across threads (actually disconnects and reconnects). Even with that, you mustn't use statement handles across threads.