PDA

View Full Version : What does QSqlDatabase::removeDatabase do exactly?



ML
19th March 2010, 01:00
I was testing the sqlbrowser example provided in the QTDIR/demos/sqlbrowser directory but somehow ran into a "segmantation fault"

Here is what I did:
1. try to connect to a bogus database by purposely providing a wrong database name,
and it return "An error occurred while opening the connection: Unknown database 'bogus' QMYSQL: Unable to connect" as expected.
2. Now, try to connect to the correct database, and I got "segmantation fault"!!

The key here is "when" this unable to connect happens... I mean if I created a successful connection on the very first try, then any subsequent attempts to make a correct/incorrect connection will just work as they are supposed to without causing any segmentation fault. However, if the very first attempt failed like when I provided a wrong database name, then the subsequent attempt to make another connection will cause the segmentation fault.

here is the code that's causing the headache..


QSqlError Browser::addConnection(const QString &driver, const QString &dbName, const QString &host,
const QString &user, const QString &passwd, int port)
{
static int cCount = 0;

QSqlError err;
QSqlDatabase db = QSqlDatabase::addDatabase(driver, QString("Browser%1").arg(++cCount));
db.setDatabaseName(dbName);
db.setHostName(host);
db.setPort(port);
if (!db.open(user, passwd)) {
err = db.lastError();
db = QSqlDatabase();
QSqlDatabase::removeDatabase(QString("Browser%1").arg(cCount));
}
connectionWidget->refresh();

return err;
}

What I found is that if I commented out "QSqlDatabase::removeDatabase(QString("Browser%1").arg(cCount));", then the segmentation fault goes away...but QSqlDatabase::connectionNames() will return both good and bad connections.....not very useful...

I also found that this seems to be happening to the Solaris platform only. As I have the same version of Qt and MySQL loaded on another Windows machine, and this segmentation faults never happened to that Windows version of sqlbrowser demo.

so the question is what does QSqlDatabase::removeDatabase ( const QString & connectionName ) do exactly other than remove the database connection connectionName from the list of database connections ? :confused:

I'm using
Qt 4.5.3
MySQL 5.1.44

any feedback is appreciated....

wysota
19th March 2010, 10:06
Qt is open-source so...


void QSqlDatabase::removeDatabase(const QString& connectionName)
{
QSqlDatabasePrivate::removeDatabase(connectionName );
}

void QSqlDatabasePrivate::removeDatabase(const QString &name)
{
QConnectionDict *dict = dbDict();
Q_ASSERT(dict);
QWriteLocker locker(&dict->lock);

if (!dict->contains(name))
return;

invalidateDb(dict->take(name), name);
}

... and ...


void QSqlDatabasePrivate::invalidateDb(const QSqlDatabase &db, const QString &name)
{
if (db.d->ref != 1) {
qWarning("QSqlDatabasePrivate::removeDatabase: connection '%s' is still in use, "
"all queries will cease to work.", name.toLocal8Bit().constData());
db.d->disable();
db.d->connName.clear();
}
}

ML
22nd March 2010, 17:45
Hi wysota,

thanks for the replay. I can see the definition of QSqlDatabase::removeDatabase. But this doesn't explain why the segmentation fault, does it? Can you duplicate the same segmentation fault when running this sqlbrowser demo on solaris or unix-like machine?

wysota
22nd March 2010, 18:41
I can see the definition of QSqlDatabase::removeDatabase. But this doesn't explain why the segmentation fault, does it?
It shows potential places and situation where such a crash could occur. As you see there is more or less nothing here that could lead to a crash. I'd say the problem is elsewhere. You can get a backtrace from the debugger to see if the crash is in your app, Qt's database driver or MySQL's client library.


Can you duplicate the same segmentation fault when running this sqlbrowser demo on solaris or unix-like machine?
I don't have solaris at hand :) If you prepare a minimal compilable example reproducing the problem, I will run it on my Linux box and see if I can reproduce it.

norobro
22nd March 2010, 19:22
Works fine here connecting to a MYSQL db on localhost. I'm on a Debian box.

ML
22nd March 2010, 22:28
To Norobro,

Did you try to connect to a bogus database on the very first try? this should return Unknown database 'bogus' QMYSQL: Unable to connect" as expected....then try to connect again...this is where the segmentation fault happens to me....

To wysota,

you should find this sqlbrowser app in the standard Qt installation directory...etc QTDIR/demos/sqlbrowser
if you don't have it...I have attached this app for you to try...

thanks for all your feedback..

norobro
22nd March 2010, 23:25
Yep. I did exactly what you described in your first post. I got real creative and used "bogus" as the db name, got the popup dialog "unable to open database", clicked ok and entered a valid db. No segfault.

ML
23rd March 2010, 00:34
I'm real confused now...Could it be the problem with QMYSQL driver? But, that doesn't make much sense because I'm able to connect successfully to the MySQL server if entered the correct database name and thereafter.....

any help is appreciated..

ML
1st April 2010, 23:33
I ran through the gdb debugger, and here is the output:

Program received signal SIGSEGV, Segmentation fault.
my_strcasecmp_8bit (cs=0x0, s=0xffffffff <Address 0xffffffff out of bounds>, t=0x6c <Address 0x6c out of bounds>) at ctype-simple.c:244
244 ctype-simple.c: No such file or directory.
in ctype-simple.c
Current language: auto; currently minimal



And from (gdb) backtrace:

my_strcasecmp_8bit (cs=0x1, s=0xffcfb6b6 <Address 0xffcfb6b6 out of bounds>, t=0x6c <Address 0x6c out of bounds>) at ctype-simple.c:244
#1 0xfd76c57c in get_charset_number (charset_name=0x69f38 "latin1", cs_flags=32) at charset.c:447
#2 0xfd76c9a0 in get_charset_by_csname (cs_name=0x69f38 "latin1", cs_flags=32, flags=16) at charset.c:564
#3 0xfd78ebfc in mysql_init_character_set (mysql=0x112b00) at client.c:1806
#4 0xfd78f5f0 in mysql_real_connect (mysql=0x112b00, host=0xfd8044cc "localhost", user=0xbcd78 "", passwd=0xe6150 "",
db=0x28 <Address 0x28 out of bounds>, port=0, unix_socket=0xfd801c6c "/tmp/mysql.sock", client_flag=3631699) at client.c:2222
#5 0xfd75c8ac in QMYSQLDriver::open () from /homes/mlin/Qt-4.5.3/plugins/sqldrivers/libqsqlmysql.so
#6 0xff346c00 in QSqlDatabase::open () from /homes/mlin/Qt-4.5.3/lib/libQtSql.so.4
#7 0x0001812c in Browser::addConnection ()
#8 0x00018b88 in Browser::addConnection ()
#9 0x0001cbb0 in Browser::qt_metacall ()
#10 0xfe00eba0 in QMetaObject::activate () from /homes/mlin/Qt-4.5.3/lib/libQtCore.so.4
#11 0xfe6258a4 in QAction::triggered () from /homes/mlin/Qt-4.5.3/lib/libQtGui.so.4
#12 0xfe625c34 in QAction::activate () from /homes/mlin/Qt-4.5.3/lib/libQtGui.so.4
#13 0xfea38cd8 in QMenuPrivate::activateCausedStack () from /homes/mlin/Qt-4.5.3/lib/libQtGui.so.4
#14 0xfea3c05c in QMenuPrivate::activateAction () from /homes/mlin/Qt-4.5.3/lib/libQtGui.so.4
#15 0xfea3efbc in QMenu::mouseReleaseEvent () from /homes/mlin/Qt-4.5.3/lib/libQtGui.so.4
#16 0xfe67ea9c in QWidget::event () from /homes/mlin/Qt-4.5.3/lib/libQtGui.so.4
#17 0xfea39974 in QMenu::event () from /homes/mlin/Qt-4.5.3/lib/libQtGui.so.4
#18 0xfe62c62c in QApplicationPrivate::notify_helper () from /homes/mlin/Qt-4.5.3/lib/libQtGui.so.4
#19 0xfe62e60c in QApplication::notify () from /homes/mlin/Qt-4.5.3/lib/libQtGui.so.4
#20 0xfdffa64c in QCoreApplication::notifyInternal () from /homes/mlin/Qt-4.5.3/lib/libQtCore.so.4
#21 0xfe62d590 in QApplicationPrivate::sendMouseEvent () from /homes/mlin/Qt-4.5.3/lib/libQtGui.so.4
#22 0xfe69d5d8 in QETWidget::translateMouseEvent () from /homes/mlin/Qt-4.5.3/lib/libQtGui.so.4
#23 0xfe69baa4 in QApplication::x11ProcessEvent () from /homes/mlin/Qt-4.5.3/lib/libQtGui.so.4
#24 0xfe6c25ec in QEventDispatcherX11::processEvents () from /homes/mlin/Qt-4.5.3/lib/libQtGui.so.4
#25 0xfdff9e44 in QEventLoop::processEvents () from /homes/mlin/Qt-4.5.3/lib/libQtCore.so.4
#26 0xfdffa000 in QEventLoop::exec () from /homes/mlin/Qt-4.5.3/lib/libQtCore.so.4
#27 0xfdfff04c in QCoreApplication::exec () from /homes/mlin/Qt-4.5.3/lib/libQtCore.so.4
#28 0x00017dfc in main ()

It seems like the problem is with the parameter pointers passed in to my_strcasecmp_8bit(). Anyone knows how to get around this problem? I installed the pre-compiled MySQL package on Solaris machine so don't necessarily have the source code to modify and rebuild the libmysqlclient_r.so.16.0.0 library.

any help is appreciated, thanks

ML

wysota
1st April 2010, 23:45
Are you using threads in your program?

ML
2nd April 2010, 00:10
This is the sqlbrowser demo example in the QTDIR/demo/sqlbrowser directory, and I don't think it is using threads.
I tried to build the Qt MySQL driver(libqsqlmysql.so) with either thread safe library "-lmysqlclient_r" or non-thread safe library "-lmysqlclient". But, it produced the same gdb output.

any idea?

thanks

ML

wysota
2nd April 2010, 00:26
To be honest I can't replicate your bug using Qt's sqlbrowser demo. Can you try to replicate the problem on a different system? Maybe you did something to your mysqlclient library or have some other incompatibility in your system...

faldzip
2nd April 2010, 10:50
For me it looks rather like mysql library problem. You can try using different version and/or compiling from scratch.