https://bugs.kde.org/show_bug.cgi?id=517865
Bug ID: 517865
Summary: KisBusyWaitBroker crashes on null qApp->thread()
during Qt global static destruction on exit
Classification: Applications
Product: krita
Version First 5.2.2
Reported In:
Platform: Ubuntu
OS: Linux
Status: REPORTED
Severity: crash
Priority: NOR
Component: General
Assignee: [email protected]
Reporter: [email protected]
Target Milestone: ---
## Summary
Krita crashes with SIGSEGV on exit. The crash occurs in KisBusyWaitBroker.cpp
at the qApp->thread() call inside notifyWaitOnImageStarted(), because qApp is
already null at that point.
## Root Cause
KisPart and QApplication are both Q_GLOBAL_STATIC objects. C++ does not
guarantee destruction order across translation units. When QApplication
destructs before KisPart, the following chain triggers:
KisPart Q_GLOBAL_STATIC Holder::~Holder() (KisPart.cpp:85)
→ KisPart::~KisPart() → delete d (KisPart.cpp:189)
→ KisAnimationCachePopulator::~KisAnimationCachePopulator()
clears priorityFrames QVector
(kis_animation_cache_populator.cpp:301)
→ KisSharedPtr<KisImage> refcount drops to 0
→ KisImage::~KisImage() → waitForDone() (kis_image.cc:316)
→ KisBusyWaitBroker::notifyWaitOnImageStarted()
→ qApp->thread() ← SIGSEGV: qApp is null (KisBusyWaitBroker.cpp:47)
The same vulnerable pattern appears 4 times in KisBusyWaitBroker.cpp:
- notifyWaitOnImageStarted() line 47
- notifyWaitOnImageEnded()
- notifyGeneralWaitStarted()
- notifyGeneralWaitEnded()
## Proposed Fix
In all four functions in libs/image/KisBusyWaitBroker.cpp, change:
if (QThread::currentThread() != qApp->thread()) return;
to:
if (!qApp || QThread::currentThread() != qApp->thread()) return;
## Stack Trace (with debug symbols)
#0 QObject::thread() const () at libQt5Core.so.5
#1 KisBusyWaitBroker::notifyWaitOnImageStarted (this=...) at
KisBusyWaitBroker.cpp:47
if (QThread::currentThread() != qApp->thread()) return;
#2 KisImage::waitForDone (this=0x5996e9a34400) at kis_image.cc:1839
KisBusyWaitBroker::instance()->notifyWaitOnImageStarted(this);
#3 KisImage::~KisImage (this=0x5996e9a34400) at kis_image.cc:316
waitForDone();
#4 KisImage::~KisImage () at kis_image.cc:320
#5 KisSharedPtr<KisImage>::deref () at kis_shared_ptr.h:194
#6 KisSharedPtr<KisImage>::~KisSharedPtr () at kis_shared_ptr.h:100
#7 QPair<KisSharedPtr<KisImage>, int>::~QPair ()
#8 QVector<QPair<KisSharedPtr<KisImage>, int>>::clear ()
#9 KisAnimationCachePopulator::~KisAnimationCachePopulator () at
kis_animation_cache_populator.cpp:301
m_d->priorityFrames.clear();
#10 KisPart::Private::~Private () at KisPart.cpp:101
#11 KisPart::~KisPart () at KisPart.cpp:189
delete d;
#12 Q_GLOBAL_STATIC KisPart Holder::~Holder() at KisPart.cpp:85
#13 __run_exit_handlers (status=0) at exit.c:108
#14 __GI_exit (status=0)
## Environment
- OS: Ubuntu 24.04 (Noble)
- Krita version: 5.2.2 (package krita 1:5.2.2+dfsg-2build8)
- Qt5Core version: 5.15.x
- Signal: SIGSEGV (11)
- Triggered by: opening a JPEG file then exiting normally
## Verification
The bug has been confirmed present and unpatched on:
- libs/image/KisBusyWaitBroker.cpp on branch master
- libs/image/KisBusyWaitBroker.cpp on branch krita/5.2
- libs/image/KisBusyWaitBroker.cpp on release/5.2.15
The file has had only 4 commits since its introduction in 2020. No existing bug
report covers this specific scenario.
--
You are receiving this mail because:
You are watching all bug changes.