Multi-threaded user app segfaults when using libpq with separate connections

From: Frank van Vugt <ftm(dot)van(dot)vugt(at)foxi(dot)nl>
To: pgsql-interfaces(at)postgresql(dot)org
Subject: Multi-threaded user app segfaults when using libpq with separate connections
Date: 2003-08-04 15:29:13
Message-ID: 200308041729.13212.ftm.van.vugt@foxi.nl
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-interfaces

Your name : Frank van Vugt
Your email address : ftm(dot)van(dot)vugt(at)foxi(dot)nl

System Configuration
---------------------
Architecture :
Intel Pentium III / Amd Athlon XP+

Operating System :
Linux 2.4.20 with glibc 2.3.2 (SuSE v8.2)

PostgreSQL version :
PostgreSQL-7.3.4

Compiler used :
gcc v3.3

Please enter a FULL description of your problem:
------------------------------------------------

A small multi-threaded demo/poc-program using Qt (including its SQL-module
which connects to PostgreSQL using libpq) is segfaulting while multiple
connections are used.

The code creates 10 new threads, each of which basically:
- locks a mutex
- adds/opens a new database connection
- unlocks the mutex
- using the newly created/opened connection
- starts a transaction
- sets transaction isolation level to SERIALIZABLE
- performs some select-only queries
- commits the transaction
- closes the database connection

Out of 10 consecutive runs, the code completes three times successfully and
segfaults the other seven times. I have recompiled libpq with debugging and
without optimization, the backtraces of the coredumps are included below.

Important : if the unlocking of the mutex is moved to AFTER the database
close, then the code seems to run without any problem each and every time

Please describe a way to repeat the problem. Please try to provide a
concise reproducible example, if at all possible:
----------------------------------------------------------------------

I'm not sure how to proceed from here. Obviously I'm using Qt for handling
PostgreSQL connections as well as multi-threading, so rewriting my
'demo-code' in plain C++ using libpthread and libpq would probably take too
much time. Maybe someone is willing to have a go at the Qt-code (just let me
know and I'll mail the source), or maybe (hopefully) the information provided
here will prove sufficient a clue to pinpoint the problem.

The only thing I found in the mailinglist archives which *may* have some
bearing to this problem is:
http://archives.postgresql.org/pgsql-interfaces/2002-09/msg00042.php

I'm not sure it's relevant, but please be advised that the PostgreSQL driver
in Qt has the following code included in order to allow compilation:

// PostgreSQL header <utils/elog.h> included by <postgres.h> redefines DEBUG.
#if defined(DEBUG)
# undef DEBUG
#endif
#include <postgres.h>
#include <libpq/libpq-fs.h>
// PostgreSQL header <catalog/pg_type.h> redefines errno erroneously.
#if defined(errno)
# undef errno
#endif
#define errno qt_psql_errno
#include <catalog/pg_type.h>
#undef errno

Furthermore, I found that the 7.4devdocs talk about the --enable-thread-safety
option for ./configure, but I don't think that applies to my platform?

=> backtraces of coredumps included below

Best,

Frank.

========================================================

The results of ten sequentially executed runs:

-+-+-+-

#0 0x40cc1b2b in realloc () from /lib/libc.so.6
(gdb) where
#0 0x40cc1b2b in realloc () from /lib/libc.so.6
#1 0x40d8c7ac in pqReadData (conn=0x80c0fc0) at fe-misc.c:483
#2 0x40d8a335 in PQgetResult (conn=0x80c0fc0) at fe-exec.c:1337
#3 0x40d8a511 in PQexec (conn=0x80c0fc0, query=0x80cb638 "set transaction
isolation level SERIALIZABLE") at fe-exec.c:1441
#4 0x4063aaa7 in QPSQLResult::reset(QString const&) (this=0x80cb418,
query=(at)0xbf7ffa9c) at sql/drivers/psql/qsql_psql.cpp:473
#5 0x4060dd34 in QSqlQuery::exec(QString const&) (this=0xbf7ffa8c,
query=(at)0xbf7ffa9c) at sql/qsqlquery.cpp:358
#6 0x08050401 in PrintEngine::run() (this=0x80a72e0) at printengine.cpp:85
#7 0x402b4be6 in QThreadInstance::start(void*) (_arg=0x80a7374) at
kernel/qthread_unix.cpp:120
#8 0x40b1dc60 in pthread_start_thread () from /lib/libpthread.so.0
(gdb)

-+-+-+-

#0 0x4061390d in QSqlDatabase::transaction() (this=0x80cd2e8) at
sql/qsqldatabase.cpp:760
760 if ( !d->driver->hasFeature( QSqlDriver::Transactions ) )
(gdb) where
#0 0x4061390d in QSqlDatabase::transaction() (this=0x80cd2e8) at
sql/qsqldatabase.cpp:760
#1 0x080503cb in PrintEngine::run() (this=0x80c0b98) at printengine.cpp:83
#2 0x402b4be6 in QThreadInstance::start(void*) (_arg=0x80c0bdc) at
kernel/qthread_unix.cpp:120
#3 0x40b1dc60 in pthread_start_thread () from /lib/libpthread.so.0
(gdb)

-+-+-+-

Third run without problems.

-+-+-+-

Fourth run without problems.

-+-+-+-

#0 0x40caf675 in fflush () from /lib/libc.so.6
(gdb) where
#0 0x40caf675 in fflush () from /lib/libc.so.6
#1 0x40d8cc16 in pqSendSome (conn=0x80c10f8) at fe-misc.c:746
#2 0x40d8cc46 in pqFlush (conn=0x80c10f8) at fe-misc.c:764
#3 0x40d896e6 in PQsendQuery (conn=0x80c10f8, query=0x80cb3d0 "set
transaction isolation level SERIALIZABLE") at fe-exec.c:799
#4 0x40d8a4f3 in PQexec (conn=0x80c10f8, query=0x80cb3d0 "set transaction
isolation level SERIALIZABLE") at fe-exec.c:1429
#5 0x4063aaa7 in QPSQLResult::reset(QString const&) (this=0x80cb0f8,
query=(at)0xbf7ffa9c) at sql/drivers/psql/qsql_psql.cpp:473
#6 0x4060dd34 in QSqlQuery::exec(QString const&) (this=0xbf7ffa8c,
query=(at)0xbf7ffa9c) at sql/qsqlquery.cpp:358
#7 0x08050401 in PrintEngine::run() (this=0x80a72d0) at printengine.cpp:85
#8 0x402b4be6 in QThreadInstance::start(void*) (_arg=0x80a7364) at
kernel/qthread_unix.cpp:120
#9 0x40b1dc60 in pthread_start_thread () from /lib/libpthread.so.0
(gdb)

-+-+-+-

#0 0x4061391e in QSqlDatabase::transaction() (this=0x80cbcb0) at
sql/qsqldatabase.cpp:760
760 if ( !d->driver->hasFeature( QSqlDriver::Transactions ) )
(gdb) where
#0 0x4061391e in QSqlDatabase::transaction() (this=0x80cbcb0) at
sql/qsqldatabase.cpp:760
#1 0x080503cb in PrintEngine::run() (this=0x80bd358) at printengine.cpp:83
#2 0x402b4be6 in QThreadInstance::start(void*) (_arg=0x80c0a74) at
kernel/qthread_unix.cpp:120
#3 0x40b1dc60 in pthread_start_thread () from /lib/libpthread.so.0
(gdb)

-+-+-+-

#0 0x403352a1 in QObject::connect(QObject const*, char const*, QObject
const*, char const*) (sender=0x80c0bf8, signal=0x80c0b58 "2destroyed()",
receiver=0x80c7660, member=0x80c0c68 "1slotResultDestroyed()")
at kernel/qobject.cpp:1737
1737 QMetaObject *smeta = sender->metaObject();
(gdb) where
#0 0x403352a1 in QObject::connect(QObject const*, char const*, QObject
const*, char const*) (sender=0x80c0bf8, signal=0x80c0b58 "2destroyed()",
receiver=0x80c7660, member=0x80c0c68 "1slotResultDestroyed()")
at kernel/qobject.cpp:1737
#1 0x4060d07d in QSqlResultShared (this=0x80c7660, result=0x80cb080) at
sql/qsqlquery.cpp:57
#2 0x4060d42f in QSqlQuery (this=0xbf7ff94c, r=0x80cb080) at
sql/qsqlquery.cpp:213
#3 0x4063c03b in QPSQLDriver::createQuery() const (this=0x80c0bf8) at
sql/drivers/psql/qsql_psql.cpp:687
#4 0x4060d874 in QSqlQuery::init(QString const&, QSqlDatabase*)
(this=0xbf7ffa8c, query=(at)0x40a26a88, db=0x80c0ae8) at sql/qsqlquery.cpp:272
#5 0x4060d762 in QSqlQuery (this=0xbf7ffa8c, db=0x80c0ae8) at
sql/qsqlquery.cpp:259
#6 0x080503dd in PrintEngine::run() (this=0x80a72e0) at printengine.cpp:84
#7 0x402b4be6 in QThreadInstance::start(void*) (_arg=0x80a7374) at
kernel/qthread_unix.cpp:120
#8 0x40b1dc60 in pthread_start_thread () from /lib/libpthread.so.0
(gdb)

-+-+-+-

#0 0x4061396d in QSqlDatabase::commit() (this=0x80c0ae8) at
sql/qsqldatabase.cpp:775
775 if ( !d->driver->hasFeature( QSqlDriver::Transactions ) )
(gdb) where
#0 0x4061396d in QSqlDatabase::commit() (this=0x80c0ae8) at
sql/qsqldatabase.cpp:775
#1 0x08050b9d in PrintEngine::run() (this=0x80a72e0) at printengine.cpp:118
#2 0x402b4be6 in QThreadInstance::start(void*) (_arg=0x80a7374) at
kernel/qthread_unix.cpp:120
#3 0x40b1dc60 in pthread_start_thread () from /lib/libpthread.so.0
(gdb)

-+-+-+-

Nineth run without problems

-+-+-+-

#0 0x40cc6a01 in strlen () from /lib/libc.so.6
(gdb) where
#0 0x40cc6a01 in strlen () from /lib/libc.so.6
#1 0x4071bf33 in internalLatin1ToUnicode (str=0xbf7ff89c "\b\021\f\b
(dot)¡(at)Äø\177¿êÀn@ (dot)¡(at)üø\177¿Dù\177¿9¬c@üø\177¿,ù\177¿\002", len=0x83ffbbd8,
maxlen=3212834996) at tools/qstring.cpp:1164
#2 0x4071cb0b in QString (this=0xbf7ff89c, str=0x83ffbbd8 <Address 0x83ffbbd8
out of bounds>) at tools/qstring.cpp:1473
#3 0x40638d4f in qMakeError (err=(at)0xbf7ff92c, type=2, p=0x80ca2d0) at
sql/drivers/psql/qsql_psql.cpp:118
#4 0x4063ac39 in QPSQLResult::reset(QString const&) (this=0x80ca5d8,
query=(at)0xbf7ffa9c) at sql/drivers/psql/qsql_psql.cpp:489
#5 0x4060dd34 in QSqlQuery::exec(QString const&) (this=0xbf7ffa8c,
query=(at)0xbf7ffa9c) at sql/qsqlquery.cpp:358
#6 0x08050401 in PrintEngine::run() (this=0x80a72e0) at printengine.cpp:85
#7 0x402b4be6 in QThreadInstance::start(void*) (_arg=0x80a7374) at
kernel/qthread_unix.cpp:120
#8 0x40b1dc60 in pthread_start_thread () from /lib/libpthread.so.0
(gdb)

-+-+-+-

Responses

Browse pgsql-interfaces by date

  From Date Subject
Next Message Tom Lane 2003-08-04 15:47:35 Re: Multi-threaded user app segfaults when using libpq with separate connections
Previous Message markw 2003-08-01 20:51:54 Re: [INTERFACES] load database from ascii files