Details
-
Bug
-
Resolution: Duplicate
-
Not Evaluated
-
5.14.2
-
None
-
macOS 10.15.6
-
-
2eba5cb403b2f2812bca5563183f42a3211c9d07
Description
OK, this is a weird one. Because of QTBUG-86874, I am trying to postpone the dealloc of the main windows in my app, having just close with no dealloc, because that fixes problems with menu item relation in the global menu bar on macOS (see that bug for more background info). Unfortunately, doing this causes a crash that seems to be a bug in Qt, although perhaps I'm doing something I shouldn't.
First of all, here's the backtrace for the crash:
1 QScopedPointer<QObjectData, QScopedPointerDeleter<QObjectData>>::operator->() const qscopedpointer.h 118 0x10201b594
2 decltype(fp.operator->()) qGetPtrHelper<QScopedPointer<QObjectData, QScopedPointerDeleter<QObjectData>> const>(QScopedPointer<QObjectData, QScopedPointerDeleter<QObjectData>> const&) qglobal.h 1133 0x10201b594
3 QObject::d_func() const qobject.h 132 0x10201b594
4 QObject::thread() const qobject.cpp 1512 0x10201b594
5 QOpenGLVertexArrayObjectPrivate::destroy() qopenglvertexarrayobject.cpp 212 0x101b21481
6 QOpenGLVertexArrayObject::destroy() qopenglvertexarrayobject.cpp 424 0x101b217cc
7 QOpenGLVertexArrayObject::~QOpenGLVertexArrayObject() qopenglvertexarrayobject.cpp 392 0x101b217c3
8 QOpenGLVertexArrayObject::~QOpenGLVertexArrayObject() qopenglvertexarrayobject.cpp 391 0x101b217b9
9 QOpenGLTextureGlyphCache::~QOpenGLTextureGlyphCache() qopengltextureglyphcache.cpp 93 0x101b1cacd
10 QOpenGLTextureGlyphCache::~QOpenGLTextureGlyphCache() qopengltextureglyphcache.cpp 88 0x101b1cbce
11 QOpenGLTextureGlyphCache::~QOpenGLTextureGlyphCache() qopengltextureglyphcache.cpp 88 0x101b1cbc9
12 QExplicitlySharedDataPointer<QFontEngineGlyphCache>::~QExplicitlySharedDataPointer() qshareddata.h 184 0x101883c92
13 QExplicitlySharedDataPointer<QFontEngineGlyphCache>::~QExplicitlySharedDataPointer() qshareddata.h 184 0x101883c74
14 QFontEngine::GlyphCacheEntry::~GlyphCacheEntry() qfontengine.cpp 1570 0x101883c74
15 QFontEngine::GlyphCacheEntry::~GlyphCacheEntry() qfontengine.cpp 1569 0x101883c74
16 void std::allocator_traits<std::allocator<std::_list_node<QFontEngine::GlyphCacheEntry, void *>>>::destroy<QFontEngine::GlyphCacheEntry>(std::integral_constant<bool, false>, std::allocator<std::_list_node<QFontEngine::GlyphCacheEntry, void *>>&, QFontEngine::GlyphCacheEntry *) memory 1732 0x101883c74
17 void std::allocator_traits<std::allocator<std::_list_node<QFontEngine::GlyphCacheEntry, void *>>>::destroy<QFontEngine::GlyphCacheEntry>(std::allocator<std::_list_node<QFontEngine::GlyphCacheEntry, void *>>&, QFontEngine::GlyphCacheEntry *) memory 1595 0x101883c74
18 std::__list_imp<QFontEngine::GlyphCacheEntry, std::allocator<QFontEngine::GlyphCacheEntry>>::clear() list 733 0x101883c74
19 std::_list_imp<QFontEngine::GlyphCacheEntry, std::allocator<QFontEngine::GlyphCacheEntry>>::~_list_imp() list 712 0x101883c24
20 std::list<QFontEngine::GlyphCacheEntry>::~list() list 805 0x101883c24
21 std::list<QFontEngine::GlyphCacheEntry>::~list() list 805 0x101883c24
22 QHashNode<void const *, std::list<QFontEngine::GlyphCacheEntry>>::~QHashNode() qhash.h 147 0x101883c24
23 QHashNode<void const *, std::list<QFontEngine::GlyphCacheEntry>>::~QHashNode() qhash.h 147 0x101883c24
24 QHash<void const *, std::list<QFontEngine::GlyphCacheEntry>>::deleteNode2(QHashData::Node *) qhash.h 563 0x101883c24
25 QHashData::free_helper(void ( *)(QHashData::Node *)) qhash.cpp 572 0x101e5db39
26 QHash<void const *, std::list<QFontEngine::GlyphCacheEntry>>::freeData(QHashData *) qhash.h 603 0x10187a47b
27 QHash<void const *, std::list<QFontEngine::GlyphCacheEntry>>::~QHash() qhash.h 250 0x10187a46f
28 QHash<void const *, std::list<QFontEngine::GlyphCacheEntry>>::~QHash() qhash.h 250 0x10187a44f
29 QFontEngine::~QFontEngine() qfontengine.cpp 277 0x10187a44f
30 QCoreTextFontEngine::~QCoreTextFontEngine() qfontengine_coretext.mm 215 0x105b7cf8e
31 QCoreTextFontEngine::~QCoreTextFontEngine() qfontengine_coretext.mm 215 0x105b7cf89
32 QFontEngineMulti::~QFontEngineMulti() qfontengine.cpp 1782 0x101880039
33 QFontEngineMulti::~QFontEngineMulti() qfontengine.cpp 1778 0x10188012e
34 QFontEngineMulti::~QFontEngineMulti() qfontengine.cpp 1778 0x101880129
35 QFontCache::clear() qfont.cpp 2861 0x1018762eb
36 QFontCache::~QFontCache() qfont.cpp 2817 0x10187603c
37 QFontCache::~QFontCache() qfont.cpp 2816 0x1018763ee
38 QFontCache::~QFontCache() qfont.cpp 2816 0x1018763e9
39 QThreadStorageData::set(void *) qthreadstorage.cpp 162 0x101e25777
40 QGuiApplicationPrivate::~QGuiApplicationPrivate() qguiapplication.cpp 1694 0x1017ca490
41 QApplicationPrivate::~QApplicationPrivate() qapplication.cpp 184 0x10116f81e
42 QApplicationPrivate::~QApplicationPrivate() qapplication.cpp 184 0x10116f819
43 QScopedPointerDeleter<QObjectData>::cleanup(QObjectData *) qscopedpointer.h 60 0x10201c06c
44 QScopedPointer<QObjectData, QScopedPointerDeleter<QObjectData>>::~QScopedPointer() qscopedpointer.h 107 0x10201c061
45 QScopedPointer<QObjectData, QScopedPointerDeleter<QObjectData>>::~QScopedPointer() qscopedpointer.h 105 0x10201c05d
46 QObject::~QObject() qobject.cpp 1119 0x10201c05d
47 QApplication::~QApplication() qapplication.cpp 837 0x101171b3d
48 main main.cpp 246 0x100012256
49 start (x86_64) /usr/lib/system/libdyld.dylib 0x7fff6b461cc9
As you can see, we're deep inside deallocations for private data held by QApplication – specifically, some kind of font glyph caching related to OpenGL rendering. I ran AddressSanitizer on this, and here's the result:
AddressSanitizer:DEADLYSIGNAL
=================================================================
==13763==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000008 (pc 0x00010bd9d594 bp 0x7ffee6d5b070 sp 0x7ffee6d5b070 T0)
==13763==The signal is caused by a READ memory access.
==13763==Hint: address points to the zero page.
#0 0x10bd9d593 in QObject::thread() const qobject.cpp:1511
#1 0x10b8a0480 in QOpenGLVertexArrayObjectPrivate::destroy() qopenglvertexarrayobject.cpp:212
#2 0x10b8a07cb in QOpenGLVertexArrayObject::~QOpenGLVertexArrayObject() qopenglvertexarrayobject.cpp:391
...
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV qobject.cpp:1511 in QObject::thread() const
==13763==ABORTING
So, this is an attempted dereference of address 0x08, which is the "d" pointer inside QScopedPointer, visible in the crash backtrace (not shown in ASAN's backtrace, I would speculate, because it is probably inlined). Of course QScopedPointer itself is not the problem here; the problem seems to be a double dealloc at some level of the object tree.
Since it seems to be related to fonts, I commented out every usage of QFont in my app, and that did indeed fix the bug – no more crash on quit. I then started uncommenting those usages one by one, but the first one I uncommented already triggered the bug again. The code in question:
static QFont *tickFont = nullptr;
if (!tickFont)
painter.setFont(*tickFont);
If I comment this out, no crash on quit; if I uncomment it, crash on quit. The tickFont variable is used only in this one spot. Although this code seems quite innocent, I thought maybe there was something naughty that I wasn't aware of about keeping a permanent QFont instance in a static local, so I tried changing it to this:
QFont tickFont;
tickFont.setPointSize(9);
painter.setFont(tickFont);
This code, surely, is not problematic; but it still crashes on quit, 100% reproducibly.
Note that this crash also happens only when I try to defer the dealloc of my main windows, by not calling setAttribute(Qt::WA_DeleteOnClose) on them, as discussed more in QTBUG-86874. If I set that attribute so they dealloc on close, then there is no crash on quit (but then the global menubar is screwed up, as discussed in the other bug).
The third important ingredient is where that font code lives: in the paintGL() method of a QOpenGLWidget subclass, where I use the painter, with the font set, to measure and draw text. That brings in the OpenGL font cache stuff that appears in the backtrace of the crash. It appears that that cached stuff somehow gets dealloced twice, if the dealloc of the main window is deferred. Or something like that; that's as far as my detective work got me, anyway. It's a pretty obscure scenario, but since it's a crash it seemed worth reporting.
Attachments
Issue Links
- duplicates
-
QTBUG-75138 Crash on exit in QOpenGLVertexArrayObject
-
- Closed
-