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

BogDan bog_dan_ro at yahoo.com
Thu Sep 25 08:10:01 CEST 2014


----- 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: Thursday, September 25, 2014 8:34 AM
Subject: Re: SV: [Development] [QML] Singletons are deleted before the other	objects

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?





Hi,

  Do we all agree that the singletons, by definition, must be available to
any object at any time until the end of the application?

  IMHO deleting first the QML singletons then the rest of the Active objects is
also wrong, because some of the active objects might need these singletons.

  I think the right way is to delete all the active objects first, then QML
singletons, try delete again all the active objects (supposing that the QML
singletons will create new objects in Component.onDestruction), then at the
very end, all the C++ singletons. IMHO this is the right way to do it, and is
not a hack at all. Doing something right, even if it's harder, is not a hack ...

  I don't see how using a weak pointer will fix the problem, who will delete
the singleton object in the end? IMHO this is a hack! I can't reference it
for every object that depends on it, because,  BTW, there are cases when the
VM doesn't delete all the objects! Yes it has lots of memleaks at the end!

Cheers,
BogDan.




More information about the Development mailing list