[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