Review Request: Fix a VLC crash by delaying object deletion to avoid invalid access by QtDBus...
Dawit A
adawit at kde.org
Sat Feb 5 19:15:03 GMT 2011
On Sat, Feb 5, 2011 at 12:57 PM, Thiago Macieira <thiago at kde.org> wrote:
> On Saturday, 5 de February de 2011 17:39:35 Dawit Alemayehu wrote:
>> was that in both cases the backtrace shows QtDBus attempting to invoke or
>> access some method or slot in the object that was just destroyed. At this
>
> That's supposed to be impossible. QtDBus connects to the object's
> destroyed(QObject*) signal, and removes the object from the object tree when
> it's destroyed.
>
> It's also thread-safe, as all manipulations of the object tree are done under
> a write lock.
The cause could be the fact that KIO itself is not really thread-safe.
I do not really know that for sure, but from what you described above,
it would seem to me to be some sort of race condition which is a
complete possibility in KIO (not thread safe). All I can say with 100%
certainty is that deferring the deletion of the objects that register
with QtDBus most definitely solves this bug, at least for me.
> The only thing I can think of is that something caused the signal to
> disconnect.
Wouldn't the object being deleted cause the disconnect ? Dunno at what
point that would happen, but as you can see from the backtraces posted
in BR# 234484, the QtDBus calls come after the object that registered
with it is destructed. Oh and I forgot to mention a very important
point. The deletion of both KBookmarkmanager and KIO::Scheduler, the
obejcts that register with QtDBus, originates from the destruction
KIO::SchedulerPrivate and KBookmarkManagerList respectively. Both
these objects are global static objects created through
K_GLOBAL_STATIC. Here is what KBookmarkManagerList's global static
marco declaration expands to:
static QBasicAtomicPointer<KBookmarkManagerList> _k_static_s_pSelf = { (0) } ;
static bool _k_static_s_pSelf_destroyed;
static struct {
inline bool isDestroyed() const { return _k_static_s_pSelf_destroyed; }
inline bool exists() const { return _k_static_s_pSelf != 0; }
inline operator KBookmarkManagerList *() { return operator->(); }
inline KBookmarkManagerList *operator->() {
if (!_k_static_s_pSelf) {
if (isDestroyed()) {
qFatal("Fatal Error: Accessed global static '%s
*%s()' after destruction. " "Defined at %s:%d",
"KBookmarkManagerList", "s_pSelf", "anonymous", 0);
}
KBookmarkManagerList *x = new KBookmarkManagerList () ;
if (!_k_static_s_pSelf.testAndSetOrdered(0, x) &&
_k_static_s_pSelf != x ) {
delete x;
} else {
static KCleanUpGlobalStatic cleanUpObject = { destroy };
}
}
return _k_static_s_pSelf;
}
inline KBookmarkManagerList &operator*() { return *operator->(); }
static void destroy() {
_k_static_s_pSelf_destroyed = true;
KBookmarkManagerList *x = _k_static_s_pSelf;
_k_static_s_pSelf = 0;
delete x;
}
} s_pSelf;
More information about the kde-core-devel
mailing list