Details
Description
Something appears to have changed in Qt 5.8.0 with the way the QMacCocoaViewContainer class has to be used? I observe the following after updating from 5.7.1 to 5.8.0 :
- Qt Designer crashes (during startup) when I have Phonon 4.9.x installed with the phonon-backend-vlc git/master backend (https://cgit.kde.org/phonon-vlc.git/).
- the QMacCocoaViewContainer ctor now also calls QMacCocoaViewContainer::setCocoaView() when a NULL NSView pointer is given.
- the QMacCocoaViewContainer example no longer releases the native view after passing it to setCocoaView(), despite what the documentation says, and despite the fact that setCocoaView indeed does a retain. Not releasing the VideoView instance in phonon-vlc's VlcMacWidget ctor also prevents the Designer crash but theoretically means the instance is being leaked.
The Designer crash is preceded by the terminal output below and occurs in ~QMacCocoaViewContainer(), when doing `[nsview release]`. This means it's doing one release too many, as confirmed by the malloc error:
qt.qpa.cocoa.window: NSView is not QNSView, consider checking for Qt::ForeignWindow qt.qpa.cocoa.window: NSView is not QNSView, consider checking for Qt::ForeignWindow Designer(97879,0x7fff721fd310) malloc: *** error for object 0x7fc7cf2a3300: pointer being freed was not allocated *** set a breakpoint in malloc_error_break to debug
I have not been able to reproduce this in other applications than Qt Designer for now.
In order to get a better idea of what's happening I added release and retain wrappers to phonon-vlc's VideoView class which produce some output. This is what I see (from the last retain call):
2017-02-17 14:03:34.738 Designer[5236:d0f] Retaining <VideoView: 0x7fd20e406a00>, count=3, caller: 1 CoreFoundation 0x00007fff83391a56 -[NSMutableArray removeObject:] + 86 2 AppKit 0x00007fff8b569321 -[NSView _removeSubview:] + 222 3 AppKit 0x00007fff8b566067 -[NSView _setSuperview:] + 824 2017-02-17 14:03:34.739 Designer[5236:d0f] Releasing <VideoView: 0x7fd20e406a00>, count=4, caller: 1 CoreFoundation 0x00007fff8333f43f CFRelease + 591 2 CoreFoundation 0x00007fff83394e3b -[__NSArrayM removeObjectAtIndex:] + 267 3 CoreFoundation 0x00007fff83391ab3 -[NSMutableArray removeObject:] + 179 4 AppKit 0x00007fff8b569321 -[NSView _removeSubview:] + 222 5 AppKit 0x00007fff8b566067 -[NSView _setSuperview:] + 824 2017-02-17 14:03:34.740 Designer[5236:d0f] Releasing <VideoView: 0x7fd20e406a00>, count=3, caller: 1 AppKit 0x00007fff8b569321 -[NSView _removeSubview:] + 222 2 AppKit 0x00007fff8b566067 -[NSView _setSuperview:] + 824 3 AppKit 0x00007fff8b568f68 -[NSView removeFromSuperview] + 332 4 AppKit 0x00007fff8b587ab0 -[NSWindow setContentView:] + 74 5 libqcocoa.dylib 0x000000010dfc9fbc _ZN12QCocoaWindowD2Ev + 332 2017-02-17 14:03:34.741 Designer[5236:d0f] Releasing <VideoView: 0x7fd20e406a00>, count=2, caller: 1 libqcocoa.dylib 0x000000010dfca23f _ZN12QCocoaWindowD2Ev + 975 2 libqcocoa.dylib 0x000000010dfca5c5 _ZThn16_N12QCocoaWindowD0Ev + 21 3 QtGui 0x0000000108dae557 _ZN7QWindow7destroyEv + 535 4 QtWidgets 0x00000001085aa8b4 _ZN14QWidgetPrivate16deleteTLSysExtraEv + 212 5 QtWidgets 0x00000001085aa58e _ZN7QWidget7destroyEbb + 830 2017-02-17 14:03:34.742 Designer[5236:d0f] Releasing <VideoView: 0x7fd20e406a00>, count=1, caller: 1 libobjc.A.dylib 0x00007fff842e265a _ZN12_GLOBAL__N_119AutoreleasePoolPage3popEPv + 502 2 CoreFoundation 0x00007fff8335e932 _CFAutoreleasePoolPop + 50 3 Foundation 0x00007fff82105437 -[NSAutoreleasePool drain] + 147 4 QtCore 0x000000010962e0b4 _ZN19QMacAutoReleasePoolD1Ev + 20 5 libqcocoa.dylib 0x000000010dfca26d _ZN12QCocoaWindowD2Ev + 1021
phonon-vlc allocates its VideoView instance within the scope of a local, temporary NSAutoreleasePool so seeing the instance being release by QMacAutoReleasePool::~QMacAutoReleasePool() surprises me a bit but is probably to be expected.
I tried to check if this is related to (mis)using ARC but the crash still occurs after converting phonon-vlc to ARC (which is just a matter of removing the explicit VideoView instance release and @autoreleasepool instead of creating one explicitly).
The crash backtrace isn't helpful with ARC:
(lldb) bt all * thread #1: tid = 0xa36530, 0x00007fff896eee20 libsystem_kernel.dylib`__wait4 + 8, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP * frame #0: 0x00007fff896eee20 libsystem_kernel.dylib`__wait4 + 8 frame #1: 0x000000011c6a9cee libKF5Crash.5.dylib`KCrash::startProcess(int, char const**, bool) [inlined] startProcessInternal(argc=<unavailable>, directly=<unavailable>) + 125 at kcrash.cpp:649 frame #2: 0x000000011c6a9c71 libKF5Crash.5.dylib`KCrash::startProcess(argc=<unavailable>, argv=<unavailable>, waitAndExit=<unavailable>) + 17 at kcrash.cpp:631 frame #3: 0x000000011c6a9ab5 libKF5Crash.5.dylib`KCrash::defaultCrashHandler(sig=11) + 1061 at kcrash.cpp:528 frame #4: 0x00007fff8961c5aa libsystem_platform.dylib`_sigtramp + 26 frame #5: 0x00007fff842e0098 libobjc.A.dylib`objc_msgSend + 24
but a bit more so without:
(lldb) bt all * thread #1: tid = 0xa37009, 0x00007fff896eee20 libsystem_kernel.dylib`__wait4 + 8, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP * frame #0: 0x00007fff896eee20 libsystem_kernel.dylib`__wait4 + 8 frame #1: 0x000000012329fcee libKF5Crash.5.dylib`KCrash::startProcess(int, char const**, bool) [inlined] startProcessInternal(argc=<unavailable>, directly=<unavailable>) + 125 at kcrash.cpp:649 frame #2: 0x000000012329fc71 libKF5Crash.5.dylib`KCrash::startProcess(argc=<unavailable>, argv=<unavailable>, waitAndExit=<unavailable>) + 17 at kcrash.cpp:631 frame #3: 0x000000012329fab5 libKF5Crash.5.dylib`KCrash::defaultCrashHandler(sig=6) + 1061 at kcrash.cpp:528 frame #4: 0x00007fff8961c5aa libsystem_platform.dylib`_sigtramp + 26 frame #5: 0x00007fff896ee867 libsystem_kernel.dylib`__pthread_kill + 11 frame #6: 0x00007fff87fc4c7c libsystem_malloc.dylib`szone_free + 2350 frame #7: 0x00007fff89cb3b26 libsystem_c.dylib`abort + 125 frame #8: 0x00007fff87fd207f libsystem_malloc.dylib`free + 411 frame #9: 0x00007fff842e23a4 libobjc.A.dylib`object_dispose + 54 frame #10: 0x00007fff8b5a0240 AppKit`-[NSResponder dealloc] + 126 frame #11: 0x00007fff8b59e35f AppKit`-[NSView dealloc] + 182 frame #12: 0x000000011bdea3ec phonon_vlc.so`-[VideoView release](self=0x00007f815d404a20, _cmd=<unavailable>) + 268 at nsvideoview.mm:91 frame #13: 0x0000000110b23f93 QtWidgets`QMacCocoaViewContainerPrivate::~QMacCocoaViewContainerPrivate() [inlined] QMacCocoaViewContainerPrivate::~QMacCocoaViewContainerPrivate(this=0x00007f815d403490) + 41 at qmaccocoaviewcontainer_mac.mm:113 frame #14: 0x0000000110b23f6a QtWidgets`QMacCocoaViewContainerPrivate::~QMacCocoaViewContainerPrivate() [inlined] QMacCocoaViewContainerPrivate::~QMacCocoaViewContainerPrivate(this=0x00007f815d403490) at qmaccocoaviewcontainer_mac.mm:110 frame #15: 0x0000000110b23f6a QtWidgets`QMacCocoaViewContainerPrivate::~QMacCocoaViewContainerPrivate(this=0x00007f815d403490) + 10 at qmaccocoaviewcontainer_mac.mm:110 frame #16: 0x000000011177e1d1 QtCore`QObject::~QObject() [inlined] QScopedPointerDeleter<QObjectData>::cleanup(pointer=<unavailable>) + 2049 at qscopedpointer.h:60 frame #17: 0x000000011177e1c6 QtCore`QObject::~QObject() [inlined] QScopedPointer<QObjectData, QScopedPointerDeleter<QObjectData> >::~QScopedPointer() + 4 at qscopedpointer.h:107 frame #18: 0x000000011177e1c2 QtCore`QObject::~QObject() [inlined] QScopedPointer<QObjectData, QScopedPointerDeleter<QObjectData> >::~QScopedPointer() at qscopedpointer.h:105 frame #19: 0x000000011177e1c2 QtCore`QObject::~QObject(this=<unavailable>) + 2034 at qobject.cpp:1049 frame #20: 0x000000011078ae00 QtWidgets`QWidget::~QWidget(this=0x00007f815d403280) + 1248 at qwidget.cpp:1714 frame #21: 0x000000011bde1d7e phonon_vlc.so`Phonon::VLC::VideoWidget::~VideoWidget() [inlined] QHash<QByteArray, double>::~QHash() + 142 at vlcmacwidget.h:25 frame #22: 0x000000011bde1d76 phonon_vlc.so`Phonon::VLC::VideoWidget::~VideoWidget() [inlined] Phonon::VLC::VideoWidget::~VideoWidget(this=0x00007f815d403280) + 125 at videowidget.cpp:206 frame #23: 0x000000011bde1cf9 phonon_vlc.so`Phonon::VLC::VideoWidget::~VideoWidget() [inlined] Phonon::VLC::VideoWidget::~VideoWidget(this=0x00007f815d403280) at videowidget.cpp:203 frame #24: 0x000000011bde1cf9 phonon_vlc.so`Phonon::VLC::VideoWidget::~VideoWidget(this=0x00007f815d403280) + 9 at videowidget.cpp:203 frame #25: 0x000000012369c5be libphonon4qt5.4.dylib`Phonon::MediaNodePrivate::~MediaNodePrivate(this=0x00007f8159479a20) + 110 at medianode.cpp:72 frame #26: 0x00000001236b1084 libphonon4qt5.4.dylib`Phonon::VideoWidgetPrivate::~VideoWidgetPrivate() [inlined] Phonon::AbstractVideoOutputPrivate::~AbstractVideoOutputPrivate() + 36 at abstractvideooutput_p.h:34 frame #27: 0x00000001236b107c libphonon4qt5.4.dylib`Phonon::VideoWidgetPrivate::~VideoWidgetPrivate() [inlined] Phonon::VideoWidgetPrivate::~VideoWidgetPrivate(this=0x00007f8159479a20) + 19 at videowidget_p.h:35 frame #28: 0x00000001236b1069 libphonon4qt5.4.dylib`Phonon::VideoWidgetPrivate::~VideoWidgetPrivate() [inlined] Phonon::VideoWidgetPrivate::~VideoWidgetPrivate(this=0x00007f8159479a20) at videowidget_p.h:35 frame #29: 0x00000001236b1069 libphonon4qt5.4.dylib`Phonon::VideoWidgetPrivate::~VideoWidgetPrivate(this=0x00007f8159479a20) + 9 at videowidget_p.h:35 frame #30: 0x00000001236b10f2 libphonon4qt5.4.dylib`Phonon::VideoWidget::~VideoWidget() [inlined] Phonon::AbstractVideoOutput::~AbstractVideoOutput() + 18 at abstractvideooutput.h:51 frame #31: 0x00000001236b10e9 libphonon4qt5.4.dylib`Phonon::VideoWidget::~VideoWidget() [inlined] Phonon::VideoWidget::~VideoWidget(this=0x00007f815946fbd0) at videowidget.h:54 frame #32: 0x00000001236b10e9 libphonon4qt5.4.dylib`Phonon::VideoWidget::~VideoWidget() [inlined] Phonon::VideoWidget::~VideoWidget(this=0x00007f815946fbd0) at videowidget.h:54 frame #33: 0x00000001236b10e9 libphonon4qt5.4.dylib`Phonon::VideoWidget::~VideoWidget(this=0x00007f815946fbd0) + 9 at videowidget.h:54 frame #34: 0x00000001101f5f76 QtDesigner`qdesigner_internal::WidgetDataBase::defaultPropertyValues(this=<unavailable>, name=<unavailable>) + 358 at widgetdatabase.cpp:444 frame #35: 0x00000001101f616a QtDesigner`qdesigner_internal::WidgetDataBase::grabDefaultPropertyValues(this=0x00007f8159506400) + 106 at widgetdatabase.cpp:453 frame #36: 0x000000010fb43c0d Designer`QDesignerWorkbench::QDesignerWorkbench(this=0x00007f815976ca40) + 317 at qdesigner_workbench.cpp:186 frame #37: 0x000000010fb40ac5 Designer`QDesigner::parseCommandLineArguments(this=0x00007fff500d6ca0) + 4613 at qdesigner.cpp:251 frame #38: 0x000000010fb3f1d8 Designer`main(argc=1, argv=<unavailable>) + 72 at main.cpp:45 frame #39: 0x00007fff8a91f5fd libdyld.dylib`start + 1 frame #40: 0x00007fff8a91f5fd libdyld.dylib`start + 1
- Also note the "qt.qpa.cocoa.window: NSView is not QNSView, consider checking for Qt::ForeignWindow" warnings. They come from qnsview_cast() . They're a bit counterproductive here because the use of non-QNSView classes is expected and intended when using QMacCocoaViewContainer. Ideally it should be at most a qCDebug() level message when QMacCocoaViewContainer or QMacNativeWidget are used.
Attachments
For Gerrit Dashboard: QTBUG-59001 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
186060,3 | macOS: Retain foreign windows | 5.9 | qt/qtbase | Status: MERGED | +2 | 0 |