> On nov. 16, 2014, 2:58 p.m., Milian Wolff wrote:
> > as I said before: Did you check whether that is actually the case? Did you
> > add some assertions to see what other thread is calling this code?
> >
> > I'm not sure whether this is supposed to be threadsafe or not. If it must
> > be threadsafe, you'll also need to make s_allowQuit threadsafe
> > (QAtomicBool).
>
> René J.V. Bertin wrote:
> I have indeed looked at this aspect, but not exhaustively and haven't
> found evidence of cross-thread reference counting. Yet.
> It's unclear what you mean with "that" (the thing actually the case). It
> "that" refers to the quitting issue, I can of course never prove that it is
> due to a reference counting race condition because the issue isn't
> reproducible reliably. I can only invalidate the idea that it is due to such
> a race condition, whenever it happens again with properly protected reference
> counting.
>
> I think we have to leave it up to the kdelibs maintainers/authors to
> decide whether or not this has to be thread safe. The doxygen documentation
> for KJob does not mention anything about thread safety. It does however note
> that *KJob and its subclasses is meant to be used in a fire-and-forget way.
> It's deleting itself when it has finished using deleteLater() so the job
> instance disappears after the next event loop run.* . It is not said that a
> KJob cannot use a KJob itself, which could lead to concurrent reference
> (de)counting, nor whether a KJob instance is guaranteed to be deleted in the
> same thread it was created, and I think that a *concurrent processing* class
> that does not explicitly mention it does thread unsafe things can be assumed
> to be thread safe.
>
> There's no QAtomicBool, btw.
>
> Milian Wolff wrote:
> As I told you before in other patches you send in: Please make sure you
> find the actual reason before changing other code in the hope of it improving
> things. If there is no hard evidence that your bug manifests itself because
> of a race in KGlobal::ref/deref, then don't change it. Adding an assertion to
> the code that its only accessed from the mainthread is done easily and should
> be hit reliably (contrary to a race condition or lock contention that Thomas
> proposes).
>
> And also note that a KJob is not neccessarily implemented using threads.
> You can also use e.g. QIODevice or external processes internally to get the
> desired behavior.
>
> René J.V. Bertin wrote:
> KJobs not using threads to implement concurrency will not cause race
> conditions in the reference counting; either they are in separate processes
> or they live in the same thread.
>
> Let me repeat once more what I also wrote in reply to Thomas below: a
> feature (like reference counting) of a framework that is frequently used in
> multithreaded applications can be expected to be thread safe. That's why my
> original description states that I consider the fact that it isn't an
> important bug regardless of whether it's the cause of my issue. Regrettably I
> am a scientist trained to give background anytime I propose something, I keep
> forgetting that there are contexts where that actually turns out
> counterproductive :(
>
> You suggest to use an assert or other detection of doing reference
> counting off the main thread, and doing so imply that reference counting
> should apparently happen only on that thread. There is no evidence that that
> is any more valid an assumption than that it should be thread safe. But I can
> do it ... only it won't tell us if multiple threads try to access the counter
> at the same time.
>
> NB: my initial proposition used about the cheapest way to get interlocked
> counting I could think of, to introduce as little side-effects as possible
> for applications that are not concerned by possible race conditions. I don't
> believe there can be any other side-effect than additional cycles (though by
> using QAtomicInt we have to assume that it is implemented correctly).
>
> René J.V. Bertin wrote:
> A little extract, seconds after relaunching KDevelop with
> ```C++
> void KGlobal::ref()
> {
> s_refCount.fetchAndAddOrdered(1);
> if ( QThread::currentThread() != qApp->thread() ) {
> qWarning() << "KGlobal::ref() called off the main thread" <<
> kBacktrace();
> }
> //kDebug() << "KGlobal::ref() : refCount = " << int(s_refCount);
> }
>
> void KGlobal::deref()
> {
> int prevRefCount = s_refCount.fetchAndAddOrdered(-1);
> if ( QThread::currentThread() != qApp->thread() ) {
> qWarning() << "KGlobal::ref() called off the main thread" <<
> kBacktrace();
> }
> //kDebug() << "KGlobal::deref() : refCount = " << int(s_refCount);
> if (prevRefCount <= 1 && int(s_allowQuit)) {
> QCoreApplication::instance()->quit();
> }
> }
> ```
>
> ```
> kdevelop(68673)/kdevelop (cpp support)
> Cpp::instantiateDeclarationAndContext: Resolved bad base-class
> "QtSharedPointer::ExternalRefCount< T >" "QtSharedPointer::ExternalRefCount<
> T >"
> kdevelop(68673)/kdevelop (cpp support)
> Cpp::instantiateDeclarationAndContext: Resolved bad base-class
> "QtSharedPointer::ExternalRefCount< T >" "QtSharedPointer::ExternalRefCount<
> T >"
> kdevelop(68673)/kdevelop (cpp support)
> Cpp::instantiateDeclarationAndContext: Resolved bad base-class
> "QtSharedPointer::ExternalRefCount< T >" "QtSharedPointer::ExternalRefCount<
> T >"
> KGlobal::ref() called off the main thread "[
> 0: 0 libkdecore.5.dylib 0x00000001000ba123
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100d89
> _ZN7KGlobal3refEv + 169
> 2: 2 libkdecore.5.dylib 0x00000001000e49f1
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000012f85f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> KGlobal::ref() called off the main thread "[
> 0: 0 libkdecore.5.dylib 0x00000001000ba123
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100d89
> _ZN7KGlobal3refEv + 169
> 2: 2 libkdecore.5.dylib 0x00000001000e49f1
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000012f85f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> KGlobal::ref() called off the main thread "[
> 0: 0 libkdecore.5.dylib 0x00000001000ba123
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100d89
> _ZN7KGlobal3refEv + 169
> 2: 2 libkdecore.5.dylib 0x00000001000e49f1
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000012f85f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> KGlobal::ref() called off the main thread "[
> 0: 0 libkdecore.5.dylib 0x00000001000ba123
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100d89
> _ZN7KGlobal3refEv + 169
> 2: 2 libkdecore.5.dylib 0x00000001000e49f1
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000012f85f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> KGlobal::ref() called off the main thread "[
> 0: 0 libkdecore.5.dylib 0x00000001000ba123
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100d89
> _ZN7KGlobal3refEv + 169
> 2: 2 libkdecore.5.dylib 0x00000001000e49f1
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000012f85f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> KGlobal::ref() called off the main thread "[
> 0: 0 libkdecore.5.dylib 0x00000001000ba123
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100d89
> _ZN7KGlobal3refEv + 169
> 2: 2 libkdecore.5.dylib 0x00000001000e49f1
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000012f85f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> KGlobal::ref() called off the main thread "[
> 0: 0 libkdecore.5.dylib 0x00000001000ba123
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100d89
> _ZN7KGlobal3refEv + 169
> 2: 2 libkdecore.5.dylib 0x00000001000e49f1
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000012f85f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> KGlobal::ref() called off the main thread "[
> 0: 0 libkdecore.5.dylib 0x00000001000ba123
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100d89
> _ZN7KGlobal3refEv + 169
> 2: 2 libkdecore.5.dylib 0x00000001000e49f1
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000012f85f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> KGlobal::ref() called off the main thread "[
> 0: 0 libkdecore.5.dylib 0x00000001000ba123
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100d89
> _ZN7KGlobal3refEv + 169
> 2: 2 libkdecore.5.dylib 0x00000001000e49f1
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000012f85f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> KGlobal::ref() called off the main thread "[
> 0: 0 libkdecore.5.dylib 0x00000001000ba123
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100d89
> _ZN7KGlobal3refEv + 169
> 2: 2 libkdecore.5.dylib 0x00000001000e49f1
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000012f85f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> KGlobal::ref() called off the main thread "[
> 0: 0 libkdecore.5.dylib 0x00000001000ba123
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100d89
> _ZN7KGlobal3refEv + 169
> 2: 2 libkdecore.5.dylib 0x00000001000e49f1
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000012f85f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> KGlobal::ref() called off the main thread "[
> 0: 0 libkdecore.5.dylib 0x00000001000ba123
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100d89
> _ZN7KGlobal3refEv + 169
> 2: 2 libkdecore.5.dylib 0x00000001000e49f1
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000012f85f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> KGlobal::ref() called off the main thread "[
> 0: 0 libkdecore.5.dylib 0x00000001000ba123
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100d89
> _ZN7KGlobal3refEv + 169
> 2: 2 libkdecore.5.dylib 0x00000001000e49f1
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000012f85f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> kdevelop(68673)/kdevelop (cpp support)
> Cpp::instantiateDeclarationAndContext: Resolved bad base-class "_List_base<
> _Tp, _Alloc >" "_List_base< _Tp, _Alloc >"
> kdevelop(68673)/kdevelop (cpp support)
> Cpp::instantiateDeclarationAndContext: Resolved bad base-class "QVector< T >"
> "QVector< T >"
> KGlobal::ref() called off the main thread "[
> 0: 0 libkdecore.5.dylib 0x00000001000ba123
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100d89
> _ZN7KGlobal3refEv + 169
> 2: 2 libkdecore.5.dylib 0x00000001000e49f1
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000012f85f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> KGlobal::ref() called off the main thread "[
> 0: 0 libkdecore.5.dylib 0x00000001000ba123
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100d89
> _ZN7KGlobal3refEv + 169
> 2: 2 libkdecore.5.dylib 0x00000001000e49f1
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000012f85f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> KGlobal::ref() called off the main thread "[
> 0: 0 libkdecore.5.dylib 0x00000001000ba123
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100d89
> _ZN7KGlobal3refEv + 169
> 2: 2 libkdecore.5.dylib 0x00000001000e49f1
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000012f85f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> KGlobal::ref() called off the main thread "[
> 0: 0 libkdecore.5.dylib 0x00000001000ba123
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100d89
> _ZN7KGlobal3refEv + 169
> 2: 2 libkdecore.5.dylib 0x00000001000e49f1
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000012f85f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> KGlobal::ref() called off the main thread "[
> 0: 0 libkdecore.5.dylib 0x00000001000ba123
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100d89
> _ZN7KGlobal3refEv + 169
> 2: 2 libkdecore.5.dylib 0x00000001000e49f1
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000012f85f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> KGlobal::ref() called off the main thread "[
> 0: 0 libkdecore.5.dylib 0x00000001000ba123
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100d89
> _ZN7KGlobal3refEv + 169
> 2: 2 libkdecore.5.dylib 0x00000001000e49f1
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000012f85f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> KGlobal::ref() called off the main thread "[
> 0: 0 libkdecore.5.dylib 0x00000001000ba123
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100d89
> _ZN7KGlobal3refEv + 169
> 2: 2 libkdecore.5.dylib 0x00000001000e49f1
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000012f85f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> ```
>
> René J.V. Bertin wrote:
> A bit more detail:
>
> ```C++
> void KGlobal::ref()
> {
> s_refCount.fetchAndAddOrdered(1);
> if ( QThread::currentThread() != qApp->thread() ) {
> qWarning() << "KGlobal::ref()=" << int(s_refCount) << "called
> from background thread" << QThread::currentThread() << "\n" << kBacktrace();
> }
> //kDebug() << "KGlobal::ref() : refCount = " << int(s_refCount);
> }
>
> void KGlobal::deref()
> {
> int prevRefCount = s_refCount.fetchAndAddOrdered(-1);
> if ( QThread::currentThread() != qApp->thread() ) {
> qWarning() << "KGlobal::deref()=" << int(s_refCount) << "called
> from background thread" << QThread::currentThread() << "\n" << kBacktrace();
> }
> //kDebug() << "KGlobal::deref() : refCount = " << int(s_refCount);
> if (prevRefCount <= 1 && int(s_allowQuit)) {
> QCoreApplication::instance()->quit();
> }
> }
> ```
>
> ```
> "
> KGlobal::ref()= 20 called from background thread QThread(0x121a40e30,
> name = "Thread (pooled)")
> "[
> 0: 0 libkdecore.5.dylib 0x00000001000b9f83
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100c4b
> _ZN7KGlobal3refEv + 267
> 2: 2 libkdecore.5.dylib 0x00000001000e4851
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000013015f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> KGlobal::ref()= 21 called from background thread QThread(0x121a40e30,
> name = "Thread (pooled)")
> "[
> 0: 0 libkdecore.5.dylib 0x00000001000b9f83
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100c4b
> _ZN7KGlobal3refEv + 267
> 2: 2 libkdecore.5.dylib 0x00000001000e4851
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000013015f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> KGlobal::ref()= 9 called from background thread QThread(0x13ebfb7b0, name
> = "Thread (pooled)")
> "[
> 0: 0 libkdecore.5.dylib 0x00000001000b9f83
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100c4b
> _ZN7KGlobal3refEv + 267
> 2: 2 libkdecore.5.dylib 0x00000001000e4851
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000013015f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> KGlobal::ref()= 10 called from background thread QThread(0x11c1b3660,
> name = "Thread (pooled)")
> "[
> 0: 0 libkdecore.5.dylib 0x00000001000b9f83
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100c4b
> _ZN7KGlobal3refEv + 267
> 2: 2 libkdecore.5.dylib 0x00000001000e4851
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000013015f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> ```
> ...
> ```
> "
> KGlobal::ref()= 269 called from background thread QThread(0x11c1b3660,
> name = "Thread (pooled)")
> "[
> 0: 0 libkdecore.5.dylib 0x00000001000b9f83
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100c4b
> _ZN7KGlobal3refEv + 267
> 2: 2 libkdecore.5.dylib 0x00000001000e4851
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000013015f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> KGlobal::ref()= 270 called from background thread QThread(0x11c1b3660,
> name = "Thread (pooled)")
> "[
> 0: 0 libkdecore.5.dylib 0x00000001000b9f83
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100c4b
> _ZN7KGlobal3refEv + 267
> 2: 2 libkdecore.5.dylib 0x00000001000e4851
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000013015f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> KGlobal::ref()= 271 called from background thread QThread(0x13ebfb7b0,
> name = "Thread (pooled)")
> "[
> 0: 0 libkdecore.5.dylib 0x00000001000b9f83
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100c4b
> _ZN7KGlobal3refEv + 267
> 2: 2 libkdecore.5.dylib 0x00000001000e4851
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000013015f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> KGlobal::ref()= 273 called from background thread QThread(0x13ebfb7b0,
> name = "Thread (pooled)")
> "[
> 0: 0 libkdecore.5.dylib 0x00000001000b9f83
> _Z14kRealBacktracei + 67
> 1: 1 libkdecore.5.dylib 0x0000000100100c4b
> _ZN7KGlobal3refEv + 267
> 2: 2 libkdecore.5.dylib 0x00000001000e4851
> _ZN4KJobC2EP7QObject + 65
> 3: 3 kdevcmakemanager.so 0x000000013015f3af
> _ZN21CMakeCommitChangesJobC1ERKN8KDevelop4PathEP12CMakeManagerPNS0_8IProjectE
> + 31
> ]
> "
> ```
> (pity so few people set thread names, or use setObjectName...)
>
> I'd say we have at least 2 threads running a cmake manager, and each
> thread *increase* the refcounter repeatedly (and in rather fast succession),
> but for now I haven't found a single `deref` that's not done off the main
> thread. Yet it has been called as can be seen above.
>
> Seems there's nothing in this scenario preventing a background thread to
> `ref()` while the main thread tries to `deref`.
>
> I'll leave it to one of you guys to try this under Linux where the
> backtrace will maybe contain a bit more useful information.
>
> Milian Wolff wrote:
> Great! That information alone is good evidence that the status quo is
> broken. A ref might clash with a deref in another thread and lead to
> undefined behavior, such as the condition reading <= 1 becoming true leading
> to the shutdown.
>
> Looking more at the code, I agree that KGlobal::ref/deref should become
> threadsafe. So if you cleanup your patch (i.e. remove the qWarning), I'm all
> for pushing this in.
>
> René J.V. Bertin wrote:
> Whew ... good thing I'm a stubborn bastard :)
>
> Just to complete the report: my test session has now finished importing
> and parsing a total of 5 projects, and to be exhaustive I requested a reload
> of one of them. Not a single deref was done off the main thread.
>
> Albert just emailed me that this ref counting mechanism is in place since
> 2006 . Surprises me a bit. True, multi-processor machines weren't that common
> by then (though I got my first in 2005, a G5 Powermac) and I guess that the
> race condition is unlikely to occur when you do multithreading on a single
> CPU core. But that situation has changed (and I've seen "my issue" occur even
> on a dual-core netbook :)).
>
> I'll clean out the code (again :)), update the diff, and then wait a bit
> for others to react before pushing it in.
>
> Milian Wolff wrote:
> You keep forgetting/confusing different things. You can use multiple
> cores / threads in an application just fine without ever noticing the issue
> at hand. It only manifests when you actually use KGlobal::(de)ref from
> different threads. Something that apparently noone ever did - besides
> KDevelop which constructs KJob's in a background thread.
Thus maybe what needs to happen is fix KDevelop?
- Albert
-----------------------------------------------------------
This is an automatically generated e-mail. To reply, visit:
https://git.reviewboard.kde.org/r/121134/#review70441
-----------------------------------------------------------
On nov. 16, 2014, 7:19 p.m., René J.V. Bertin wrote:
>
> -----------------------------------------------------------
> This is an automatically generated e-mail. To reply, visit:
> https://git.reviewboard.kde.org/r/121134/
> -----------------------------------------------------------
>
> (Updated nov. 16, 2014, 7:19 p.m.)
>
>
> Review request for KDE Software on Mac OS X and kdelibs.
>
>
> Repository: kdelibs
>
>
> Description
> -------
>
> I have been experiencing unexpected exits from KDevelop that were not due to
> any kind of error in the KDevelop code; it was as if someone told the
> application to exit normally. This happens mostly on OS X, but also sometimes
> on Linux.
> I finally traced this to `KGlobal::deref` reaching a zero reference count and
> invoking `QCoreApplication::quit` when called from one of KDevelop's KJob
> dtors. There does not appear to be a reference counting mismatch in the code,
> so the issue might be due to a race condition in KGlobal::ref/deref.
>
> This patch introduces thread-safety to KGlobal's reference counting by
> turning the simple global `static int s_refCount` into a `static QAtomicInt
> s_refCount`. I consider this an important bug fix regardless of whether it
> corrects the issue I have with KDevelop.
>
>
> Diffs
> -----
>
> kdecore/kernel/kglobal.cpp cf003a4
>
> Diff: https://git.reviewboard.kde.org/r/121134/diff/
>
>
> Testing
> -------
>
> On OS X 10.6.8 only for now.
>
> NB: Qt itself uses the QAtomicInt's parent class (QBasicAtomicInt) for its
> own reference counter used for implicit sharing. This is thus well-tested
> code that is unlikely to introduce regressions to a core KDE feature.
>
>
> Thanks,
>
> René J.V. Bertin
>
>