[Development] [QML] Singletons are deleted before the other objects

Simon Hausmann simon.hausmann at digia.com
Thu Sep 25 07:34:28 CEST 2014


On Monday, September 22, 2014 02:28:06 AM BogDan wrote:
> ----- Original Message -----
> From: Simon Hausmann <simon.hausmann at digia.com>
> To: BogDan <bog_dan_ro at yahoo.com>
> Cc: Chris Adams <chris.adams at qinetic.com.au>; Qt Development Group
> <development at qt-project.org> Sent: Monday, September 22, 2014 11:56 AM
> Subject: Re: SV: [Development] [QML] Singletons are deleted before the
> other	objects
> On Monday 22. September 2014 01.33.14 BogDan wrote:
> > On Monday 22. September 2014 01.19.17 BogDan wrote:
> > > Hi Simon,
> > > 
> > > I took a look and I'm pretty sure I'm right ;-). BTW I'm using 5.4
> > > branch (sha1 f9ee33f96), is a little  bit old, but I bet nobody
> > > fixed it. The same problem is in previous releases.
> > > 
> > > So, the singletons are deleted in QQmlEngine::~QQmlEngine():910
> > > The other active objects are deleted in  MemoryManager::sweep(*true*)
> > > which is called by MemoryManager::~MemoryManager()
> > > which is called by ExecutionEngine::~ExecutionEngine()
> > > which is called by QV8Engine::~QV8Engine()
> > > which is called by QJSEngine::~QJSEngine()
> > > which is called *after* QQmlEngine::~QQmlEngine()
> > > 
> > > Check the call-stack:
> > > 0   MyObject::~MyObject myobject.cpp    44  0x7fffd141eb4b
> > > 1   MyObject::~MyObject myobject.cpp    46  0x7fffd141ec8a
> > > 2   (anonymous namespace)::QObjectDeleter::~QObjectDeleter
> > > qv4qobjectwrapper.cpp   1018    0x7ffff5f79ee1  f9ee33f96f9ee33f96 3
> > > (anonymous namespace)::QObjectDeleter::~QObjectDeleter
> > > qv4qobjectwrapper.cpp   1021    0x7ffff5f79f2e 4
> > > QV4::MemoryManager::sweep   qv4mm.cpp   377 0x7ffff5efd080
> > > 5   QV4::MemoryManager::~MemoryManager  qv4mm.cpp   515 0x7ffff5efda18
> > > 6   QV4::ExecutionEngine::~ExecutionEngine  qv4engine.cpp   421
> > > 0x7ffff5ee4f54 7   QV8Engine::~QV8Engine   qv8engine.cpp   116
> > > 0x7ffff606b7f2
> > > 8   QV8Engine::~QV8Engine   qv8engine.cpp   117 0x7ffff606b87e
> > > 9   QJSEngine::~QJSEngine   qjsengine.cpp   203 0x7ffff5e64b1e
> > > 10  QQmlEngine::~QQmlEngine qqmlengine.cpp  893 0x7ffff5fb0b5d
> > > 11  QQmlEngine::~QQmlEngine qqmlengine.cpp  916 0x7ffff5fb0b8c
> > > 12  QObjectPrivate::deleteChildren  qobject.cpp 1943    0x7ffff599efd0
> > > 13  QObject::~QObject   qobject.cpp 1034    0x7ffff599d760
> > > 14  QWindow::~QWindow   qwindow.cpp 210 0x7ffff63f5bdc
> > > 15  QQuickWindow::~QQuickWindow qquickwindow.cpp    1099   
> > > 0x7ffff6bc0353
> > > 16  QQuickView::~QQuickView qquickview.cpp  220 0x7ffff6c9fe35
> > > 17  main    main.cpp    12  0x4021fb
> > > 
> > > IMHO the sequence from QQmlEngine::~QQmlEngine():910 should be moved
> > > after/in MemoryManager::~MemoryManager ...
> > 
> > Ahh, so what you're talking about are the _JavaScript_ wrappers for the
> > singletons, not the singleton objects themselves. That explains the
> > confusion.
> > 
> > Yes, due to the inheritance the final garbage collection runs as the very
> > last step - and it has to, conceptually. I'm wondering: What code do you
> > have running at that point that gets still called? Is it code in C++
> > destructors?
> > 
> > 
> > 
> > 
> > 
> > 
> > Yes, the code from their destructors needs the singletons objects which
> > are
> > not available anymore.
> 
> When are those destructors called?
> 
> We need a little bit more information here, because it isn't obvious how to
> solve this. There's naturally a pool of objects around that haven't been
> garbage collected. On engine shutdown the garbage collector sweeps them all,
> and there's naturally no way to define an order of destruction if you think
> of such an environment.
> 
> 
> 
> 
> 
> I know that there is a pool of active objects, what I think is wrong is to
> delete the register singletons before you delete these objects.
> 
> 
> The active objects destructors are called by MemoryManager::sweep.
> These objects register themselves in the singleton object when they are
> created and they must unregister themselves in the destructor when they
> are deleted. But as you seen the singletons are deleted before, so there is
> no way to properly unregister themselves! This is why I believe that the
> singletons must be the very last objects that are deleted (just like in
> any other languages).
> 
> So, my proposal is to move the singletons deletion from
> QmlEngine::~QQmlEngine():910 to another place which is called after
> MemoryManager::sweep(*true*) is doing its job.
> 
> I'd like to mention one more thing, the singletons and the other objects
> are register in a standalone plugin.
> 
> Please let me know if you need more info.

I think I see what you mean now. The main issue I have with this is that it 
would break singletons written in QML. Just like C++ they may also have
their Component.onDestruction handlers, and those would naturally not be
callable anymore after such a move. Not calling those anymore would be a 
change in behavior.

I'm not convinced that this is a change for the better TBH. Of course we could
try to delete first the QML singletons, then the rest of the JavaScript world
and then finally the C++ singletons. But you have to admit, that starting to 
feel like a bunch of hacks.

Instead of relying on an order of destruction, why not reference your C++
object with a weak pointer?


Simon



More information about the Development mailing list