segfault in QSqlDatabase::database when used in the destructor of a static variable when closing the app
-
Hi,
I'm getting this crash inQSqlDatabase::database
when closing my app#0 0x00007ffff5128e54 in std::__atomic_base<QReadWriteLockPrivate*>::compare_exchange_strong(QReadWriteLockPrivate*&, QReadWriteLockPrivate*, std::memory_order, std::memory_order) (__m2=std::memory_order_acquire, __m1=std::memory_order_acquire, __p2=0x1, __p1=@0x7fffffffe418: 0x0, this=0x8) at /opt/rh/devtoolset-4/root/usr/include/c++/5.3.1/bits/atomic_base.h:752 #1 0x00007ffff5128e54 in std::atomic<QReadWriteLockPrivate*>::compare_exchange_strong(QReadWriteLockPrivate*&, QReadWriteLockPrivate*, std::memory_order, std::memory_order) (__m2=std::memory_order_acquire, __m1=std::memory_order_acquire, __p2=0x1, __p1=@0x7fffffffe418: 0x0, this=0x8) at /opt/rh/devtoolset-4/root/usr/include/c++/5.3.1/atomic:462 #2 0x00007ffff5128e54 in QAtomicOps<QReadWriteLockPrivate*>::testAndSetAcquire<QReadWriteLockPrivate*>(std::atomic<QReadWriteLockPrivate*>&, QReadWriteLockPrivate*, QReadWriteLockPrivate*, QReadWriteLockPrivate**) (currentValue=0x0, newValue=0x1, expectedValue=0x0, _q_value=...) at ../../include/QtCore/../../src/corelib/thread/qatomic_cxx11.h:290 #3 0x00007ffff5128e54 in QBasicAtomicPointer<QReadWriteLockPrivate>::testAndSetAcquire(QReadWriteLockPrivate*, QReadWriteLockPrivate*) (newValue=0x1, expectedValue=0x0, this=this@entry=0x8) at ../../include/QtCore/../../src/corelib/thread/qbasicatomic.h:254 #4 0x00007ffff5128e54 in QReadWriteLock::lockForRead() (this=this@entry=0x8) at thread/qreadwritelock.cpp:176 #5 0x00007ffff758e66a in QSqlDatabasePrivate::database(QString const&, bool) (name=..., open=<optimized out>) at kernel/qsqldatabase.cpp:229 db = {static defaultConnection = 0x7ffff75b0dc7 "qt_sql_default_connection", d = 0x8} #6 0x00007ffff758e8dc in QSqlDatabase::database(QString const&, bool) (connectionName=..., open=<optimized out>) at kernel/qsqldatabase.cpp:493 #7 0x00007ffff7f15ffe in Database::close() () at /github/qrop/core/dbutils/db.cpp:182 database = {static defaultConnection = 0x7ffff75b0dc7 "qt_sql_default_connection", d = 0x1} __PRETTY_FUNCTION__ = "static void Database::close()" query = {d = 0x7ffff58189b8 <(anonymous namespace)::Q_QGS_qt_factory_loaders::innerFunction()::holder>} #8 0x00007ffff7ef5bc2 in Qrop::~Qrop() (this=0x5555557604a0 <Singleton<Qrop>::instance()::instance>, __in_chrg=<optimized out>) at /github/qrop/core/qrop.cpp:37 #9 0x00007ffff4ba2d8c in __run_exit_handlers (status=0, listp=0x7ffff4d24718 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true, run_dtors=run_dtors@entry=true) at exit.c:108 atfct = <optimized out> onfct = <optimized out> cxafct = <optimized out> f = <optimized out> new_exitfn_called = 556 cur = 0x7fffd000ff90 #10 0x00007ffff4ba2eba in __GI_exit (status=<optimized out>) at exit.c:139 #11 0x00007ffff4b8d0a2 in __libc_start_main (main=0x55555556f414 <main(int, char**)>, argc=1, argv=0x7fffffffe748, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe738) at ../csu/libc-start.c:342 result = <optimized out> unwind_buf = {cancel_jmp_buf = {{jmp_buf = {0, 6269653140045944320, 93824992336064, 140737488348992, 0, 0, 168635527937512960, 168616228171011584}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x7fffffffe758, 0x7ffff7ffe190}, data = {prev = 0x0, cleanup = 0x0, canceltype = -6312}}} not_first_call = <optimized out> #12 0x000055555556d8ea in _start ()
I've a C++ static singleton that is getting deleted at the end when the application is closed (GUI app in QML). In its destructor I'm calling inderectly
QSqlDatabase::database
(cf here)If my object is not deleted at the end of the program as a static variable but before in an handle on
QCoreApplication::aboutToQuit
I don't have the crash (using a static pointer that I choose to delete rather than a static variable)
Any idea if it could come from that or is it completely unrelated? -
As mentioned every time when someone is using a QSqlDatabase instance as member - don't do it. It's properly documented how to use QSqlDatabase:
Warning: It is highly recommended that you do not keep a copy of the QSqlDatabase around as a member of a class, as this will prevent the instance from being correctly cleaned up on shutdown. If you need to access an existing QSqlDatabase, it should be accessed with database(). If you chose to have a QSqlDatabase member variable, this needs to be deleted before the QCoreApplication instance is deleted, otherwise it may lead to undefined behavior.
-
As mentioned every time when someone is using a QSqlDatabase instance as member - don't do it. It's properly documented how to use QSqlDatabase:
Warning: It is highly recommended that you do not keep a copy of the QSqlDatabase around as a member of a class, as this will prevent the instance from being correctly cleaned up on shutdown. If you need to access an existing QSqlDatabase, it should be accessed with database(). If you chose to have a QSqlDatabase member variable, this needs to be deleted before the QCoreApplication instance is deleted, otherwise it may lead to undefined behavior.
@Christian-Ehrlicher
I don't use a QSqlDatabase instance as a member... I'm usingQSqlDatabase::database
static method and it is this one that crashes...
but thanks, I guess I got my answer withthis needs to be deleted before the QCoreApplication instance is deleted
I supposeQSqlDatabase::database
can't be used after that theQCoreApplication
has been deleted too. this could be added to the documentation of the method...
That is my case I guess calling it in my static singleton destructor. -
@Christian-Ehrlicher
I don't use a QSqlDatabase instance as a member... I'm usingQSqlDatabase::database
static method and it is this one that crashes...
but thanks, I guess I got my answer withthis needs to be deleted before the QCoreApplication instance is deleted
I supposeQSqlDatabase::database
can't be used after that theQCoreApplication
has been deleted too. this could be added to the documentation of the method...
That is my case I guess calling it in my static singleton destructor. -
@Christian-Ehrlicher
I don't use a QSqlDatabase instance as a member... I'm usingQSqlDatabase::database
static method and it is this one that crashes...
but thanks, I guess I got my answer withthis needs to be deleted before the QCoreApplication instance is deleted
I supposeQSqlDatabase::database
can't be used after that theQCoreApplication
has been deleted too. this could be added to the documentation of the method...
That is my case I guess calling it in my static singleton destructor.@mbruel said in segfault in QSqlDatabase::database when used in the destructor of a static variable when closing the app:
This could be added to the documentation of the method...
Then you have to add this to >90% of all Qt functions...
-
@Christian-Ehrlicher
I don't use a QSqlDatabase instance as a member... I'm usingQSqlDatabase::database
static method and it is this one that crashes...
but thanks, I guess I got my answer withthis needs to be deleted before the QCoreApplication instance is deleted
I supposeQSqlDatabase::database
can't be used after that theQCoreApplication
has been deleted too. this could be added to the documentation of the method...
That is my case I guess calling it in my static singleton destructor.@mbruel said in segfault in QSqlDatabase::database when used in the destructor of a static variable when closing the app:
I suppose QSqlDatabase::database can't be used after that the QCoreApplication has been deleted too. this could be added to the documentation of the method...
AFAIK, in documentation, you will found that
QCoreApplication
/QGuiApplication
/QApplication
must be the first object to create before doing anything with Qt classes.
It holds global information which are used by most of Qt classes and also the main event loop.So it is implicit, to me, that it should be the last which should be destroyed.
-
@mbruel said in segfault in QSqlDatabase::database when used in the destructor of a static variable when closing the app:
I suppose QSqlDatabase::database can't be used after that the QCoreApplication has been deleted too. this could be added to the documentation of the method...
AFAIK, in documentation, you will found that
QCoreApplication
/QGuiApplication
/QApplication
must be the first object to create before doing anything with Qt classes.
It holds global information which are used by most of Qt classes and also the main event loop.So it is implicit, to me, that it should be the last which should be destroyed.
@KroMignon
Purely OOI (untested), doesn't this apply to something likeQObject
classes? Can you use, say, aQVector
outside ofQ...Application
, or is even that not allowed? -
@KroMignon
Purely OOI (untested), doesn't this apply to something likeQObject
classes? Can you use, say, aQVector
outside ofQ...Application
, or is even that not allowed?@JonB said in segfault in QSqlDatabase::database when used in the destructor of a static variable when closing the app:
Purely OOI (untested), doesn't this apply to something like QObject classes? Can you use, say, a QVector outside of Q...Application, or is even that not allowed?
Especially QObject classes!
A good coding practice with Qt is to first createQCoreApplication
/QGuiApplication
/QApplication
at beginning ofmain()
, in fact you don't really have to destroy it.int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); QCoreApplication::setApplicationName("..."); QCoreApplication::setOrganizationName("..."); QCoreApplication::setApplicationVersion("1.0.0"); // continue initialization ... // start main loop and wait application end return app.exec(); }
-
@mbruel
I guess it's taken you shouldn't try to use most things Qt afterQ...Application
is destroyed. Like you could try to still use aQWidget
, but I wouldn't recommend it....@JonB said in segfault in QSqlDatabase::database when used in the destructor of a static variable when closing the app:
I guess it's taken you shouldn't try to use most things Qt after Q...Application is destroyed. Like you could try to still use a QWidget, but I wouldn't recommend it....
well for
QObject
that uses the event loop definitely butQSqlDatabase
doesn't seem to be aQObject
...
and in general I obviously don't do this kind of things but using a static singleton as the Main app that would do some work on Database on its destructor could really happen... I guess in that case it should own theQApplication
and delete it as the latest. On the project I'm working on it is not the case, theQApplication
is defined in themain.cpp
.@JonB said in segfault in QSqlDatabase::database when used in the destructor of a static variable when closing the app:
Purely OOI (untested), doesn't this apply to something like QObject classes? Can you use, say, a QVector outside of Q...Application, or is even that not allowed?
I believe you could use QVector and other Qt objects without a QApplication. I didn't test but I don't see why not... as long as they don't use the event loop...
@KroMignon said in segfault in QSqlDatabase::database when used in the destructor of a static variable when closing the app:
A good coding practice with Qt is to first create QCoreApplication/QGuiApplication/QApplication at beginning of main(), in fact you don't really have to destroy it.
well in general yes... for small programs. but it is quite common to rather embed the
QCoreApplication/QGuiApplication/QApplication
in the Object representing your application, especially if you parse the command line and can either launch a GUI or stay PURE command line (onlyQCoreApplication
)
you can find an example of such main.cpp here where my app derives from CmdOrGuiApp. -
Don't use global static singletons.
-
@JonB said in segfault in QSqlDatabase::database when used in the destructor of a static variable when closing the app:
I guess it's taken you shouldn't try to use most things Qt after Q...Application is destroyed. Like you could try to still use a QWidget, but I wouldn't recommend it....
well for
QObject
that uses the event loop definitely butQSqlDatabase
doesn't seem to be aQObject
...
and in general I obviously don't do this kind of things but using a static singleton as the Main app that would do some work on Database on its destructor could really happen... I guess in that case it should own theQApplication
and delete it as the latest. On the project I'm working on it is not the case, theQApplication
is defined in themain.cpp
.@JonB said in segfault in QSqlDatabase::database when used in the destructor of a static variable when closing the app:
Purely OOI (untested), doesn't this apply to something like QObject classes? Can you use, say, a QVector outside of Q...Application, or is even that not allowed?
I believe you could use QVector and other Qt objects without a QApplication. I didn't test but I don't see why not... as long as they don't use the event loop...
@KroMignon said in segfault in QSqlDatabase::database when used in the destructor of a static variable when closing the app:
A good coding practice with Qt is to first create QCoreApplication/QGuiApplication/QApplication at beginning of main(), in fact you don't really have to destroy it.
well in general yes... for small programs. but it is quite common to rather embed the
QCoreApplication/QGuiApplication/QApplication
in the Object representing your application, especially if you parse the command line and can either launch a GUI or stay PURE command line (onlyQCoreApplication
)
you can find an example of such main.cpp here where my app derives from CmdOrGuiApp.@mbruel said in segfault in QSqlDatabase::database when used in the destructor of a static variable when closing the app:
well in general yes... for small programs. but it is quite common to rather embed the QCoreApplication/QGuiApplication/QApplication in the Object representing your application, especially if you parse the command line and can either launch a GUI or stay PURE command line (only QCoreApplication)
you can find an example of such main.cpp here where my app derives from CmdOrGuiApp.No this is not common!
You never have to useQObject
before creatingQCoreApplication/QGuiApplication/QApplication
.
Of course, sometimes you want to parse command line before creating one of those, but when doing this, you do not use QObject based classes but only C++ standard functions like this example taken from Qt documentation:QCoreApplication* createApplication(int &argc, char *argv[]) { for (int i = 1; i < argc; ++i) { if (!qstrcmp(argv[i], "-no-gui")) return new QCoreApplication(argc, argv); } return new QApplication(argc, argv); } int main(int argc, char* argv[]) { QScopedPointer<QCoreApplication> app(createApplication(argc, argv)); if (qobject_cast<QApplication *>(app.data())) { // start GUI version... } else { // start non-GUI version... } return app->exec(); }
-
Don't use global static singletons.
@Christian-Ehrlicher said in segfault in QSqlDatabase::database when used in the destructor of a static variable when closing the app:
Don't use global static singletons.
A Singleton class like this is quite useful and there is no issue with it as you can connect
QCoreApplication::aboutToQuit
to the deletion of its instance if needed (so before the destruction of theQCoreApplication
).
It's a matter of taste, personally I find it really convenient to be able to use a singleton usingMyObject::instance()
rather than having to provide an handle to it (either in function calls or in the constructor and storing it as a member)@KroMignon said in segfault in QSqlDatabase::database when used in the destructor of a static variable when closing the app:
You never have to use QObject before creating QCoreApplication/QGuiApplication/QApplication.
Of course, sometimes you want to parse command line before creating one of those, but when doing this, you do not use QObject based classes but only C++ standard functions like this example taken from Qt documentationwell of course you don't have to use a
QObject
, but who says you shouldn't if it is convenient for you?...
If you lookQCoreApplication
documentation, its main goal is to provide an event loop for your application (main thread).
There is no issue creatingQObject
before or without it as long as you don't uses events, is there?
I've done few softwares where I create my mainQObject
that will instantiate theQCoreApplication
and it's working just fine. This main object is then able to use the event queue...
I don't understand why you would say we shouldn't do that, what is the reason?
Some people even inherit fromQCoreApplication
but for what I read few years ago, it was more advised to initiate it (and own it) than subclassing (this allowing to be able to choose which instance you need depending on whatever condition) -
@Christian-Ehrlicher said in segfault in QSqlDatabase::database when used in the destructor of a static variable when closing the app:
Don't use global static singletons.
A Singleton class like this is quite useful and there is no issue with it as you can connect
QCoreApplication::aboutToQuit
to the deletion of its instance if needed (so before the destruction of theQCoreApplication
).
It's a matter of taste, personally I find it really convenient to be able to use a singleton usingMyObject::instance()
rather than having to provide an handle to it (either in function calls or in the constructor and storing it as a member)@KroMignon said in segfault in QSqlDatabase::database when used in the destructor of a static variable when closing the app:
You never have to use QObject before creating QCoreApplication/QGuiApplication/QApplication.
Of course, sometimes you want to parse command line before creating one of those, but when doing this, you do not use QObject based classes but only C++ standard functions like this example taken from Qt documentationwell of course you don't have to use a
QObject
, but who says you shouldn't if it is convenient for you?...
If you lookQCoreApplication
documentation, its main goal is to provide an event loop for your application (main thread).
There is no issue creatingQObject
before or without it as long as you don't uses events, is there?
I've done few softwares where I create my mainQObject
that will instantiate theQCoreApplication
and it's working just fine. This main object is then able to use the event queue...
I don't understand why you would say we shouldn't do that, what is the reason?
Some people even inherit fromQCoreApplication
but for what I read few years ago, it was more advised to initiate it (and own it) than subclassing (this allowing to be able to choose which instance you need depending on whatever condition)@mbruel said in segfault in QSqlDatabase::database when used in the destructor of a static variable when closing the app:
I don't understand why you would say we shouldn't do that, what is the reason?
I am only sharing my experience with you, if you think it is not relevant to you, never mind. This is not a problem for me.
And if you look to QCoreApplication documentation, you will find this:
In general, we recommend that you create a QCoreApplication, QGuiApplication or a QApplication object in your main() function as early as possible. exec() will not return until the event loop exits; e.g., when quit() is called.
The reason is to avoid having to find strange bugs in your application, like qDebug() not working (which I had to find some years ago).
-
@mbruel said in segfault in QSqlDatabase::database when used in the destructor of a static variable when closing the app:
I don't understand why you would say we shouldn't do that, what is the reason?
I am only sharing my experience with you, if you think it is not relevant to you, never mind. This is not a problem for me.
And if you look to QCoreApplication documentation, you will find this:
In general, we recommend that you create a QCoreApplication, QGuiApplication or a QApplication object in your main() function as early as possible. exec() will not return until the event loop exits; e.g., when quit() is called.
The reason is to avoid having to find strange bugs in your application, like qDebug() not working (which I had to find some years ago).
@KroMignon well you were quite affirmative in your replies...
I care of other people experiences and opinions but we're also here to understand what's possible, what's advised, what's not advised and most of all what's not possible preferably with a concrete explanation -
@KroMignon well you were quite affirmative in your replies...
I care of other people experiences and opinions but we're also here to understand what's possible, what's advised, what's not advised and most of all what's not possible preferably with a concrete explanation@mbruel said in segfault in QSqlDatabase::database when used in the destructor of a static variable when closing the app:
well you were quite affirmative in your replies...
I care of other people experiences and opinions but we're also here to understand what's possible, what's advised, what's not advised and most of all what's not possible preferably with a concrete explanationSorry about that, I am a french guy living in Germany and writing in english... Sometimes there are too many languages in my head and I don't find the right words.
I will try to take more care about my writing to be less directive.But this was a really hard bug to find, only because I create QCoreApplication too late in my
main()
-
@mbruel said in segfault in QSqlDatabase::database when used in the destructor of a static variable when closing the app:
well you were quite affirmative in your replies...
I care of other people experiences and opinions but we're also here to understand what's possible, what's advised, what's not advised and most of all what's not possible preferably with a concrete explanationSorry about that, I am a french guy living in Germany and writing in english... Sometimes there are too many languages in my head and I don't find the right words.
I will try to take more care about my writing to be less directive.But this was a really hard bug to find, only because I create QCoreApplication too late in my
main()
@KroMignon
pas de problèmes ;)
yeah it's defo something unusual that can bring unexpected issues and/or crashes...