Bug 430322 - Crash on exit with tabbed diagrams enabled
Summary: Crash on exit with tabbed diagrams enabled
Status: RESOLVED FIXED
Alias: None
Product: umbrello
Classification: Applications
Component: general (show other bugs)
Version: Git
Platform: Other Linux
: NOR normal
Target Milestone: ---
Assignee: Umbrello Development Group
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-12-12 22:03 UTC by Oliver Kellogg
Modified: 2021-02-11 23:37 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In: 2.33.80 (KDE releases 21.03.80)


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Oliver Kellogg 2020-12-12 22:03:11 UTC
SUMMARY

After import of a large Rose MDL file with very many diagrams, Umbrello crashed on exit.
In Settings -> Configure Umbrello -> General Settings "Miscellaneous", "Use tabbed diagrams" had been active.

STEPS TO REPRODUCE
1. Start Umbrello, ensure that "Use tabbed diagrams" is activated.
2. Load a model with very many diagrams (in my case resulting form a
   Rose model import - but may also happen in other usage scenarios)
3. Click around, select different diagrams, perhaps rearrange some diagram
   objects
4. Select File -> Quit or press the mainwindow "X" corner symbol
5. On dialog "The current file has been modified. Do you want to save it?"
   press Discard.


OBSERVED RESULT

Segfault with following backtrace:

#4  in std::__atomic_base<int>::operator++() (this=0x7f379ab77901 <typeinfo name for QFutureWatcherBase+17>) at /usr/include/c++/10/bits/atomic_base.h:326
#5  in QAtomicOps<int>::ref<int>(std::atomic<int>&) (_q_value=...) at /usr/include/qt5/QtCore/qatomic_cxx11.h:283
#6  in QBasicAtomicInteger<int>::ref() (this=0x7f379ab77901 <typeinfo name for QFutureWatcherBase+17>) at /usr/include/qt5/QtCore/qbasicatomic.h:118
#7  in QtPrivate::RefCount::ref() (this=0x7f379ab77901 <typeinfo name for QFutureWatcherBase+17>) at /usr/include/qt5/QtCore/qrefcount.h:61
#8  in QString::QString(QString const&) (this=0x7ffc93c3e568, other=...) at /usr/include/qt5/QtCore/qstring.h:1094
#9  in UMLScene::documentation() const (this=0x7f3790028f20) at /u/umbrello/umlscene.cpp:359
#10 in DocWindow::isModified() (this=0x203c700) at /u/umbrello/docwindow.cpp:353
#11 in DocWindow::updateDocumentation(bool, bool) (this=0x203c700, clear=true, startup=false) at /u/umbrello/docwindow.cpp:278
#12 in DocWindow::showDocumentation(UMLScene*, bool) (this=0x203c700, scene=0xd6da320, overwrite=false) at /u/umbrello/docwindow.cpp:185
#13 in UMLDoc::changeCurrentView(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) (this=0x1a23be0, id="49A5573701AF") at /u/umbrello/umldoc.cpp:1790
#14 in UMLApp::slotTabChanged(int) (this=0x18fec30, index=0) at /u/umbrello/uml.cpp:3199
#15 in UMLApp::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) (_o=0x18fec30, _c=QMetaObject::InvokeMetaMethod, _id=81, _a=0x7ffc93c3e910) at /u/build/umbrello/libumbrello_autogen/EWIEGA46WW/moc_uml.cpp:560
#16 in doActivate<false>(QObject*, int, void**) (sender=0x1f48d80, signal_index=7, argv=argv@entry=0x7ffc93c3e910) at ../../include/QtCore/../../src/corelib/kernel/qobjectdefs_impl.h:395
#17 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) (sender=<optimized out>, m=m@entry=0x7f379bbd68c0 <QTabWidget::staticMetaObject>, local_signal_index=local_signal_index@entry=0, argv=argv@entry=0x7ffc93c3e910) at kernel/qobject.cpp:3946
#18 in QTabWidget::currentChanged(int) (this=<optimized out>, _t1=<optimized out>) at .moc/moc_qtabwidget.cpp:326
#19 in doActivate<false>(QObject*, int, void**) (sender=0x1f51020, signal_index=7, argv=argv@entry=0x7ffc93c3ea30) at ../../include/QtCore/../../src/corelib/kernel/qobjectdefs_impl.h:395
#20 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) (sender=sender@entry=0x1f51020, m=m@entry=0x7f379bbd5320 <QTabBar::staticMetaObject>, local_signal_index=local_signal_index@entry=0, argv=argv@entry=0x7ffc93c3ea30) at kernel/qobject.cpp:3946
#21 in QTabBar::currentChanged(int) (this=this@entry=0x1f51020, _t1=<optimized out>, _t1@entry=0) at .moc/moc_qtabbar.cpp:338
#22 in QTabBar::setCurrentIndex(int) (this=this@entry=0x1f51020, index=index@entry=0) at widgets/qtabbar.cpp:1450
#23 in QTabBar::removeTab(int) (this=0x1f51020, index=<optimized out>, index@entry=0) at widgets/qtabbar.cpp:1094
#24 in QTabWidgetPrivate::_q_removeTab(int) (index=0, this=<optimized out>) at widgets/qtabwidget.cpp:802
#25 QTabWidget::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) (_o=<optimized out>, _c=<optimized out>, _id=<optimized out>, _a=<optimized out>) at .moc/moc_qtabwidget.cpp:178
#26 0x00007f379aac78a0 in doActivate<false>(QObject*, int, void**) (sender=0x1f50b40, signal_index=8, argv=argv@entry=0x7ffc93c3ec10) at ../../include/QtCore/../../src/corelib/kernel/qobjectdefs_impl.h:395
#27 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) (sender=<optimized out>, m=m@entry=0x7f379bbd4d00 <QStackedWidget::staticMetaObject>, local_signal_index=local_signal_index@entry=1, argv=argv@entry=0x7ffc93c3ec10) at kernel/qobject.cpp:3946
#28 in QStackedWidget::widgetRemoved(int) (this=<optimized out>, _t1=<optimized out>) at .moc/moc_qstackedwidget.cpp:226
#29 in doActivate<false>(QObject*, int, void**) (sender=0x1f50a50, signal_index=3, argv=argv@entry=0x7ffc93c3ed30) at ../../include/QtCore/../../src/corelib/kernel/qobjectdefs_impl.h:395
#30 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) (sender=sender@entry=0x1f50a50, m=m@entry=0x7f379bbc5360 <QStackedLayout::staticMetaObject>, local_signal_index=local_signal_index@entry=0, argv=argv@entry=0x7ffc93c3ed30) at kernel/qobject.cpp:3946
#31 in QStackedLayout::widgetRemoved(int) (this=this@entry=0x1f50a50, _t1=<optimized out>, _t1@entry=0) at .moc/moc_qstackedlayout.cpp:220
#32 in QStackedLayout::takeAt(int) (this=0x1f50a50, index=0) at kernel/qstackedlayout.cpp:280
#33 in removeWidgetRecursively(QLayoutItem*, QObject*) (li=<optimized out>, w=0xd71e8c0) at kernel/qlayout.cpp:573
#34 in QLayout::widgetEvent(QEvent*) (this=<optimized out>, e=e@entry=0x7ffc93c3ee90) at ../../include/QtCore/../../src/corelib/kernel/qcoreevent.h:354
#35 in QApplicationPrivate::notify_helper(QObject*, QEvent*) (this=<optimized out>, receiver=0x1f50b40, e=0x7ffc93c3ee90) at kernel/qapplication.cpp:3621
#36 in QCoreApplication::notifyInternal2(QObject*, QEvent*) (receiver=0x1f50b40, event=0x7ffc93c3ee90) at ../../include/QtCore/5.15.2/QtCore/private/../../../../../src/corelib/thread/qthread_p.h:325
#37 in QObjectPrivate::setParent_helper(QObject*) (this=0xd701ec0, o=0x0) at kernel/qobject.cpp:2149
#38 in QObject::~QObject() (this=<optimized out>, __in_chrg=<optimized out>) at kernel/qobject.cpp:1093
#39 in UMLView::~UMLView() (this=0xd71e8c0, __in_chrg=<optimized out>) at /u/umbrello/umlview.cpp:48
#40 in UMLView::~UMLView() (this=0xd71e8c0, __in_chrg=<optimized out>) at /u/umbrello/umlview.cpp:51
#41 in qDeleteAll<QList<QPointer<UMLView> >::const_iterator>(QList<QPointer<UMLView> >::const_iterator, QList<QPointer<UMLView> >::const_iterator) (begin=..., end=...) at /usr/include/qt5/QtCore/qalgorithms.h:320
#42 in qDeleteAll<QList<QPointer<UMLView> > >(QList<QPointer<UMLView> > const&) (c=...) at /usr/include/qt5/QtCore/qalgorithms.h:328
#43 in UMLFolder::~UMLFolder() (this=0xd6d9cc0, __in_chrg=<optimized out>) at /u/umbrello/uml1model/folder.cpp:52
#44 in UMLFolder::~UMLFolder() (this=0xd6d9cc0, __in_chrg=<optimized out>) at /u/umbrello/uml1model/folder.cpp:54
#45 in UMLPackage::removeAllObjects() (this=0xbc3abc0) at /u/umbrello/uml1model/package.cpp:259
#46 in UMLPackage::removeAllObjects() (this=0x91ac220) at /u/umbrello/uml1model/package.cpp:257
#47 in UMLPackage::removeAllObjects() (this=0x91a6150) at /u/umbrello/uml1model/package.cpp:257
#48 in UMLPackage::removeAllObjects() (this=0x21b81a0) at /u/umbrello/uml1model/package.cpp:257
#49 in UMLPackage::removeAllObjects() (this=0x1c6db50) at /u/umbrello/uml1model/package.cpp:257
#50 in UMLDoc::removeAllObjects() (this=0x1a23be0) at /u/umbrello/umldoc.cpp:2931
#51 in UMLDoc::closeDocument() (this=0x1a23be0) at /u/umbrello/umldoc.cpp:432
#52 in UMLDoc::saveModified() (this=0x1a23be0) at /u/umbrello/umldoc.cpp:386
#53 in UMLApp::queryClose() (this=0x18fec30) at /u/umbrello/uml.cpp:1235
#54 in KMainWindow::closeEvent(QCloseEvent*) () at /usr/lib64/libKF5XmlGui.so.5


EXPECTED RESULT

Don't crash.

SOFTWARE/OS VERSIONS
Umbrello: git master @ 526bd5ac
Linux/KDE Plasma: openSuSE Tumbleweed 20201129
KDE Plasma Version: 5.20.3
KDE Frameworks Version: 5.76.0
Qt Version: 5.15.2
Comment 1 Oliver Kellogg 2020-12-12 23:59:25 UTC
Git commit 9d9800c31411b0c8b0cf253c0dfddc62fbaa7d2d by Oliver Kellogg.
Committed on 12/12/2020 at 23:51.
Pushed by okellogg into branch 'master'.

Fix for 'Crash on exit with tabbed diagrams enabled'

umbrello/uml.cpp
- In function slotTabChanged(int index) / slotTabChanged(QWidget* tab)
  do not call m_doc->changeCurrentView() is s_shuttingDown is true.
  Reason: Calling changeCurrentView accesses objects which have already
  been deconstructed.

M  +2    -2    umbrello/uml.cpp

https://invent.kde.org/sdk/umbrello/commit/9d9800c31411b0c8b0cf253c0dfddc62fbaa7d2d
Comment 2 Oliver Kellogg 2020-12-13 16:31:33 UTC
Git commit bd8b3b1c9f2ccbd54b7fb34d95db8e6d8d94df0b by Oliver Kellogg.
Committed on 13/12/2020 at 16:30.
Pushed by okellogg into branch 'master'.

Followup to commit 9d9800c fix for crash on exit with tabbed diagrams

There was a further crash on closing in the code path
  UMLApp::slotFileClose() => slotFileNew() => m_doc->newDocument()
due to DiagramsModel::m_views not having been reset to empty.
This caused access to stale UMLView objects already deconstructed.

umbrello/models/diagramsmodel.{h,cpp}
- New function removeAllDiagrams clears content of m_views.

umbrello/uml.cpp
- In function slotFileClose call diagramsModel()->removeAllDiagrams()
  on m_doc before calling slotFileNew().

M  +10   -0    umbrello/models/diagramsmodel.cpp
M  +1    -0    umbrello/models/diagramsmodel.h
M  +2    -0    umbrello/uml.cpp

https://invent.kde.org/sdk/umbrello/commit/bd8b3b1c9f2ccbd54b7fb34d95db8e6d8d94df0b