> On Jan. 12, 2016, 10:49 p.m., David Faure wrote:
> > Can I see the backtrace, with a description of how this gets triggered? I'm 
> > not sure the issue is fully understood (as shown by the use of "might" in 
> > the description...).
> > 
> > Is the action being destroyed by clicking into a submenu of the action? 
> > Otherwise I don't get the relation with the fix.
> 
> René J.V. Bertin wrote:
>     A CrashReporter backtrace I still had logged:
>     
>     ```
>     Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
>     Exception Codes: EXC_I386_GPFLT
>     
>     Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
>     0   org.qt-project.QtCore                 0x000000010cbac886 
> QObject::property(char const*) const + 150 (qlist.h:105)
>     1   libqcocoa.dylib                       0x000000011189e37a 
> QCocoaMenuItem::~QCocoaMenuItem() + 58 (qcocoamenuitem.mm:109)
>     2   libqcocoa.dylib                       0x000000011189e52e 
> QCocoaMenuItem::~QCocoaMenuItem() + 14 (qcocoamenuitem.mm:106)
>     3   org.qt-project.QtWidgets              0x000000010b2989bd 
> QMenu::actionEvent(QActionEvent*) + 749 (qmenu.cpp:3224)
>     4   org.qt-project.QtWidgets              0x000000010b1643d0 
> QWidget::event(QEvent*) + 1232 (qwidget.cpp:9044)
>     5   org.qt-project.QtWidgets              0x000000010b296bdc 
> QMenu::event(QEvent*) + 1164 (qmenu.cpp:2678)
>     6   org.qt-project.QtWidgets              0x000000010b12653b 
> QApplicationPrivate::notify_helper(QObject*, QEvent*) + 251 
> (qapplication.cpp:3716)
>     7   org.qt-project.QtWidgets              0x000000010b1298f4 
> QApplication::notify(QObject*, QEvent*) + 8212 (qapplication.cpp:3681)
>     8   org.qt-project.QtCore                 0x000000010cb7b433 
> QCoreApplication::notifyInternal(QObject*, QEvent*) + 115 (qthread_p.h:291)
>     9   org.qt-project.QtWidgets              0x000000010b1582ed 
> QWidget::removeAction(QAction*) + 125 (qcoreapplication.h:224)
>     10  org.qt-project.QtWidgets              0x000000010b11c711 
> QAction::~QAction() + 97 (qaction.cpp:566)
>     11  org.qt-project.QtWidgets              0x000000010b16d16c 
> QWidgetAction::~QWidgetAction() + 444 (qwidgetaction.cpp:122)
>     12  libKF5WidgetsAddons.5.dylib           0x000000010acddd80 
> KSelectAction::~KSelectAction() + 64 (kselectaction.cpp:99)
>     13  org.qt-project.QtCore                 0x000000010cba3d75 
> QObjectPrivate::deleteChildren() + 245 (qobject.cpp:1943)
>     14  org.qt-project.QtWidgets              0x000000010b153ee1 
> QWidget::~QWidget() + 1441 (qwidget.cpp:1658)
>     15                                        0x00000001093c16bb Bin::~Bin() 
> + 1067 (bin.cpp:456)
>     16                                        0x00000001093c181e Bin::~Bin() 
> + 14 (bin.cpp:438)
>     17                                        0x0000000109443d3e 
> Core::~Core() + 62 (core.cpp:43)
>     18                                        0x000000010940c95f 
> MainWindow::~MainWindow() + 207 (mainwindow.cpp:549)
>     19                                        0x000000010940cd45 
> MainWindow::~MainWindow() + 21 (mainwindow.cpp:542)
>     20  org.qt-project.QtCore                 0x000000010cba4748 
> QObject::event(QEvent*) + 776 (qobject.cpp:4455)
>     21  org.qt-project.QtWidgets              0x000000010b164d26 
> QWidget::event(QEvent*) + 3622 (qwidget.cpp:9105)
>     22  org.qt-project.QtWidgets              0x000000010b26c45f 
> QMainWindow::event(QEvent*) + 911 (qmainwindow.cpp:1495)
>     23  libKF5XmlGui.5.dylib                  0x000000010a81e810 
> KMainWindow::event(QEvent*) + 624 (kmainwindow.cpp:829)
>     24  libKF5XmlGui.5.dylib                  0x000000010a856398 
> KXmlGuiWindow::event(QEvent*) + 24 (kxmlguiwindow.cpp:118)
>     25  org.qt-project.QtWidgets              0x000000010b12653b 
> QApplicationPrivate::notify_helper(QObject*, QEvent*) + 251 
> (qapplication.cpp:3716)
>     26  org.qt-project.QtWidgets              0x000000010b1298f4 
> QApplication::notify(QObject*, QEvent*) + 8212 (qapplication.cpp:3681)
>     27  org.qt-project.QtCore                 0x000000010cb7c0db 
> QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) + 971 
> (qthread_p.h:291)
>     28  org.qt-project.QtCore                 0x000000010cb7ba2c 
> QCoreApplication::exec() + 412 (qcoreapplication.cpp:1240)
>     29                                        0x00000001093f3761 main + 10257 
> (main.cpp:118)
>     30  libdyld.dylib                         0x00007fff8508c5fd start + 1
>     ```
>     
>     When I say crash-on-exit, I mean that the crash occurs after selecting 
> the Quit menu item, or closing the main window.
> 
> René J.V. Bertin wrote:
>     Here's a backtrace obtained in the debugger:
>     
>     ```
>     * thread #1: tid = 0x3727c3, 0x0000000103c4e886 
> QtCore`QObject::property(char const*) const [inlined] QListData::size() const 
> + 4 at qlist.h:105, queue = 'com.apple.main-thread', stop reason = 
> EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
>         frame #0: 0x0000000103c4e886 QtCore`QObject::property(char const*) 
> const [inlined] QListData::size() const + 4 at qlist.h:105
>        102      void remove(int i);
>        103      void remove(int i, int n);
>        104      void move(int from, int to);
>     -> 105      inline int size() const { return d->end - d->begin; }
>        106      inline bool isEmpty() const { return d->end  == d->begin; }
>        107      inline void **at(int i) const { return d->array + d->begin + 
> i; }
>        108      inline void **begin() const { return d->array + d->begin; }
>     (lldb) bt
>     * thread #1: tid = 0x3727c3, 0x0000000103c4e886 
> QtCore`QObject::property(char const*) const [inlined] QListData::size() const 
> + 4 at qlist.h:105, queue = 'com.apple.main-thread', stop reason = 
> EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
>       * frame #0: 0x0000000103c4e886 QtCore`QObject::property(char const*) 
> const [inlined] QListData::size() const + 4 at qlist.h:105
>         frame #1: 0x0000000103c4e882 QtCore`QObject::property(char const*) 
> const [inlined] QList<QByteArray>::indexOf(this=0x0000000118b9a1c0, 
> t=0x0000000118b9a1c0, from=<unavailable>) const at qlist.h:940
>         frame #2: 0x0000000103c4e882 
> QtCore`QObject::property(this=<unavailable>, name=0x000000010af1799a) const + 
> 146 at qobject.cpp:3884
>         frame #3: 0x000000010ae9e37a 
> libqcocoa.dylib`QCocoaMenuItem::~QCocoaMenuItem(this=0x00000001069bd9d0) + 58 
> at qcocoamenuitem.mm:109
>         frame #4: 0x000000010ae9e52e 
> libqcocoa.dylib`QCocoaMenuItem::~QCocoaMenuItem() [inlined] 
> QCocoaMenuItem::~QCocoaMenuItem(this=0x00000001069bd9d0) + 14 at 
> qcocoamenuitem.mm:106
>         frame #5: 0x000000010ae9e529 
> libqcocoa.dylib`QCocoaMenuItem::~QCocoaMenuItem(this=0x00000001069bd9d0) + 9 
> at qcocoamenuitem.mm:106
>         frame #6: 0x00000001022339bd 
> QtWidgets`QMenu::actionEvent(this=0x00000001069bce00, e=<unavailable>) + 749 
> at qmenu.cpp:3224
>         frame #7: 0x00000001020ff3d0 
> QtWidgets`QWidget::event(this=0x00000001069bce00, event=0x00007fff5fbfde30) + 
> 1232 at qwidget.cpp:9044
>         frame #8: 0x0000000102231bdc 
> QtWidgets`QMenu::event(this=0x00000001069bce00, e=0x00007fff5fbfde30) + 1164 
> at qmenu.cpp:2678
>         frame #9: 0x00000001020c153b 
> QtWidgets`QApplicationPrivate::notify_helper(this=<unavailable>, 
> receiver=0x00000001069bce00, e=0x00007fff5fbfde30) + 251 at 
> qapplication.cpp:3716
>         frame #10: 0x00000001020c48f4 
> QtWidgets`QApplication::notify(this=<unavailable>, receiver=<unavailable>, 
> e=<unavailable>) + 8212 at qapplication.cpp:3681
>         frame #11: 0x0000000103c1d433 
> QtCore`QCoreApplication::notifyInternal(this=<unavailable>, 
> receiver=<unavailable>, event=<unavailable>) + 115 at qcoreapplication.cpp:970
>         frame #12: 0x00000001020f32ed 
> QtWidgets`QWidget::removeAction(QAction*) [inlined] 
> QCoreApplication::sendEvent(receiver=<unavailable>, event=0x00000001037c1480) 
> + 125 at qcoreapplication.h:224
>         frame #13: 0x00000001020f32ce 
> QtWidgets`QWidget::removeAction(this=<unavailable>, 
> action=0x0000000106a7eff0) + 94 at qwidget.cpp:3317
>         frame #14: 0x00000001020b7711 
> QtWidgets`QAction::~QAction(this=0x0000000106a7eff0) + 97 at qaction.cpp:568
>         frame #15: 0x000000010210816c 
> QtWidgets`QWidgetAction::~QWidgetAction(this=0x0000000106a7eff0) + 444 at 
> qwidgetaction.cpp:122
>         frame #16: 0x0000000101db9d80 
> libKF5WidgetsAddons.5.dylib`KSelectAction::~KSelectAction() [inlined] 
> KSelectAction::~KSelectAction(this=0x0000000106a7eff0) + 64 at 
> kselectaction.cpp:107
>         frame #17: 0x0000000101db9d49 
> libKF5WidgetsAddons.5.dylib`KSelectAction::~KSelectAction() [inlined] 
> KSelectAction::~KSelectAction(this=0x0000000106a7eff0) at kselectaction.cpp:99
>         frame #18: 0x0000000101db9d49 
> libKF5WidgetsAddons.5.dylib`KSelectAction::~KSelectAction(this=0x0000000106a7eff0)
>  + 9 at kselectaction.cpp:99
>         frame #19: 0x0000000103c45d75 
> QtCore`QObjectPrivate::deleteChildren(this=0x0000000106a78e30) + 245 at 
> qobject.cpp:1946
>         frame #20: 0x00000001020eeee1 
> QtWidgets`QWidget::~QWidget(this=0x0000000106a78c80) + 1441 at 
> qwidget.cpp:1658
>         frame #21: 0x0000000100363e6b 
> kdenlive`Bin::~Bin(this=0x0000000106a78c80) + 1067 at bin.cpp:458
>         frame #22: 0x0000000100363fce kdenlive`Bin::~Bin() [inlined] 
> Bin::~Bin(this=0x0000000106a78c80) + 14 at bin.cpp:440
>         frame #23: 0x0000000100363fc9 
> kdenlive`Bin::~Bin(this=0x0000000106a78c80) + 9 at bin.cpp:440
>         frame #24: 0x00000001003e8bed kdenlive`Core::~Core() [inlined] 
> Core::~Core(this=0x0000000106a6ba60) + 68 at core.cpp:47
>         frame #25: 0x00000001003e8ba9 kdenlive`Core::~Core() [inlined] 
> Core::~Core(this=0x0000000106a6ba60) at core.cpp:43
>         frame #26: 0x00000001003e8ba9 
> kdenlive`Core::~Core(this=0x0000000106a6ba60) + 9 at core.cpp:43
>         frame #27: 0x00000001003bbb8f 
> kdenlive`MainWindow::~MainWindow(this=0x0000000106b4df40, 
> vtt=0x00000001004e1850) + 207 at mainwindow.cpp:614
>         frame #28: 0x00000001003bbf75 kdenlive`MainWindow::~MainWindow() 
> [inlined] MainWindow::~MainWindow(this=0x0000000106b4df40) + 12 at 
> mainwindow.cpp:608
>         frame #29: 0x00000001003bbf69 
> kdenlive`MainWindow::~MainWindow(this=0x0000000106b4df40) + 9 at 
> mainwindow.cpp:608
>         frame #30: 0x0000000103c46748 QtCore`QObject::event(QEvent*) 
> [inlined] qDeleteInEventHandler(o=0x0000000106b4df40) + 14 at qobject.cpp:4455
>         frame #31: 0x0000000103c4673a 
> QtCore`QObject::event(this=0x0000000106b4df40, e=<unavailable>) + 762 at 
> qobject.cpp:1230
>         frame #32: 0x00000001020ffd26 
> QtWidgets`QWidget::event(this=0x0000000106b4df40, event=0x00000001236a90d0) + 
> 3622 at qwidget.cpp:9105
>         frame #33: 0x000000010220745f 
> QtWidgets`QMainWindow::event(this=0x0000000106b4df40, 
> event=0x00000001236a90d0) + 911 at qmainwindow.cpp:1495
>         frame #34: 0x0000000101925810 
> libKF5XmlGui.5.dylib`KMainWindow::event(this=0x0000000106b4df40, 
> ev=0x00000001236a90d0) + 624 at kmainwindow.cpp:829
>         frame #35: 0x000000010195d398 
> libKF5XmlGui.5.dylib`KXmlGuiWindow::event(this=0x0000000106b4df40, 
> ev=0x00000001236a90d0) + 24 at kxmlguiwindow.cpp:118
>         frame #36: 0x00000001020c153b 
> QtWidgets`QApplicationPrivate::notify_helper(this=<unavailable>, 
> receiver=0x0000000106b4df40, e=0x00000001236a90d0) + 251 at 
> qapplication.cpp:3716
>         frame #37: 0x00000001020c48f4 
> QtWidgets`QApplication::notify(this=<unavailable>, receiver=<unavailable>, 
> e=<unavailable>) + 8212 at qapplication.cpp:3681
>         frame #38: 0x0000000103c1e0db 
> QtCore`QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) 
> [inlined] QCoreApplication::notifyInternal(this=<unavailable>, 
> receiver=<unavailable>, event=<unavailable>) + 95 at qcoreapplication.cpp:970
>         frame #39: 0x0000000103c1e07c 
> QtCore`QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) 
> [inlined] QCoreApplication::sendEvent(receiver=<unavailable>, 
> event=0x00000001236a90d0) + 28 at qcoreapplication.h:224
>         frame #40: 0x0000000103c1e060 
> QtCore`QCoreApplicationPrivate::sendPostedEvents(receiver=0x0000000000000000, 
> event_type=0, data=0x0000000106a00e70) + 848 at qcoreapplication.cpp:1598
>         frame #41: 0x0000000103c1da2c QtCore`QCoreApplication::exec() + 412 
> at qcoreapplication.cpp:1240
>         frame #42: 0x00000001003a13b1 kdenlive`main(argc=1, 
> argv=<unavailable>) + 9841 at main.cpp:126
>         frame #43: 0x00007fff8508c5fd libdyld.dylib`start + 1
>         frame #44: 0x00007fff8508c5fd libdyld.dylib`start + 1
>     ```
> 
> David Faure wrote:
>     Ok I see clearly what's happening. ~KSelectAction deletes QAction::menu() 
> (the child menu), then (in ~QAction) the action is removed from its own 
> (parent) menu, and the implementation of that on OSX is to delete a "platform 
> menuitem", which has this code
>         if (m_menu && COCOA_MENU_ANCESTOR(m_menu) == this)
>             SET_COCOA_MENU_ANCESTOR(m_menu, 0);
>     i.e. reparent any child menu. At this point m_menu is dangling, hence the 
> crash. (technically m_menu is a "platform menu" but 
>     
>     So 1) moving the "delete d_ptr" of KSelectAction is completely useless 
> and unrelated. The crash happens *after* ~KSelectAction itself is done.
>     2) setMenu(0), and just that, is a possible fix
>     3) menu()->deleteLater, and just that, is a possible fix
>     
>     (oh crap I forgot to submit this yesterday morning).
>     
>     Let's see how this matches your new comment. Yep, it does.
>     I vote for 3), to avoid the overhead of 2).

> (technically m_menu is a "platform menu" but

but ?

> So 1) moving the "delete d_ptr" of KSelectAction is completely useless and 
> unrelated.

I still think it's good practice to delete d-ptrs last O:^) but maybe there's 
even more and better reason to delete them first?


I suppose you checked if and how `m_menu` gets handled appropriately when using 
deleteLater (and also if there's indeed overhead to setMenu when called with a 
NULL pointer)?

This reparenting is getting to be a real PITA. I thought it only prevent 
QWidgetActions from being used in multiple menus, but I've been seeing "this 
item is already part of menu X" more and more, also for regular QAction 
instances ... and often it actually claims that the current and destination 
menus are the same. That last bit may mean that I made an error in adding 
detail to the error message, but may also correspond to a KDE "thing" to 
rebuild the same menu over and over again.


- René J.V.


-----------------------------------------------------------
This is an automatically generated e-mail. To reply, visit:
https://git.reviewboard.kde.org/r/126725/#review90980
-----------------------------------------------------------


On Jan. 12, 2016, 2:14 p.m., René J.V. Bertin wrote:
> 
> -----------------------------------------------------------
> This is an automatically generated e-mail. To reply, visit:
> https://git.reviewboard.kde.org/r/126725/
> -----------------------------------------------------------
> 
> (Updated Jan. 12, 2016, 2:14 p.m.)
> 
> 
> Review request for KDE Frameworks and Christoph Feck.
> 
> 
> Repository: kwidgetsaddons
> 
> 
> Description
> -------
> 
> I was seeing a systematic crash on exitting kdenlive5, on OS X deep under the 
> `delete menu()` instruction in `KSelectAction::~KSelectAction`. The backtrace 
> suggested this might be due to a pending event (or an event due to the menu 
> deletion) being delivered post-mortem to an instance of a QMenu related class.
> 
> My fix is based on 3 principles:
> 1) release the "foreign" member instance (`menu()`) before releasing the own 
> d-ptr
> 2) Remove the QMenu instance from ourselves before deleting it to have one 
> less potential dangling reference to it
> 3) QMenu is a QObject descendent that corresponds to a UI element: on OS X it 
> is safer to dispose these through `deleteLater()` rather than directly.
> 
> 
> Diffs
> -----
> 
>   src/kselectaction.cpp 1381099 
> 
> Diff: https://git.reviewboard.kde.org/r/126725/diff/
> 
> 
> Testing
> -------
> 
> On OS X 10.9.5, Qt 5.5.1 and KF5 Frameworks 5.16.0, built for installation 
> under /opt/local .
> 
> It seems that points 1) and 2) above already solve the crash issue in 
> kdenlive on OS X, but the general principle stands so I suggest keeping 3) in 
> library code like this.
> 
> 
> Thanks,
> 
> René J.V. Bertin
> 
>

_______________________________________________
Kde-frameworks-devel mailing list
Kde-frameworks-devel@kde.org
https://mail.kde.org/mailman/listinfo/kde-frameworks-devel

Reply via email to