Commit 08e204a4 authored by Harald Sitter's avatar Harald Sitter 🏳️‍🌈
Browse files

discard wayland client crashes following compositor crash

when the compositor goes down Qt will abort the clients causing kind of
erroneous crashes that the client can't do anything about. as such we
don't want to allow these reports from going through and instead
shortcut the report dialog to a final conclusion page where we inform
the user about the unfortunate circumstance surrounding this crash.

compositor crash detection is based on a simple check for the relevant
qfatalizing string resulting in a persistent state on the parser

BUG: 431561
parent c2854551
/*******************************************************************
* reportassistantdialog.cpp
* SPDX-FileCopyrightText: 2009, 2010 Dario Andres Rodriguez <andresbajotierra@gmail.com>
* SPDX-FileCopyrightText: 2019 Harald Sitter <sitter@kde.org>
* SPDX-FileCopyrightText: 2019-2021 Harald Sitter <sitter@kde.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*
......@@ -280,6 +280,13 @@ void ReportAssistantDialog::next()
// Force save settings in current page
page->aboutToHide();
// Qt aborts clients when the wayland compositor crashes. We can't do anything with these reports and immediately
// jump to the conclusion page. Additional handling happens there.
if (DrKonqi::debuggerManager()->backtraceGenerator()->parser()->hasCompositorCrashed()) {
setCurrentPage(m_pageWidgetMap.value(QLatin1String(PAGE_CONCLUSIONS_ID)));
return;
}
// If the crash is worth reporting and it is BKO, skip the Conclusions page
if (m_reportInterface->isWorthReporting() && DrKonqi::crashedApplication()->bugReportAddress().isKdeBugzilla()) {
// Depending on whether the page is appropriate either go to version
......
......@@ -2,6 +2,7 @@
* reportassistantpages_base.cpp
* SPDX-FileCopyrightText: 2009 Dario Andres Rodriguez <andresbajotierra@gmail.com>
* SPDX-FileCopyrightText: 2009 A. L. Spehr <spehr@kde.org>
* SPDX-FileCopyrightText: 2021 Harald Sitter <sitter@kde.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*
......@@ -202,6 +203,10 @@ ConclusionPage::ConclusionPage(ReportAssistantDialog *parent)
"report information about this crash.")));
connect(ui.m_showReportInformationButton, &QPushButton::clicked, this, &ConclusionPage::openReportInformation);
connect(ui.m_explanationLabel, &QLabel::linkActivated, this, [](const QString &link) {
QDesktopServices::openUrl(QUrl(link));
});
ui.m_restartAppOnFinish->setVisible(false);
}
......@@ -246,6 +251,26 @@ void ConclusionPage::aboutToShow()
m_needToReport = reportInterface()->isWorthReporting() && !isDuplicate;
emitCompleteChanged();
if (DrKonqi::debuggerManager()->backtraceGenerator()->parser()->hasCompositorCrashed()) {
ui.m_conclusionsLabel->setText(i18nc("@info",
"It appears that this crash is actually the result of an earlier crash in the compositor and cannot be "
"submitted as it lacks the required information to resolve the problem."));
ui.m_explanationLabel->setText(xi18nc(
"@info",
"KDE developers would appreciate if you could find and attach the crash log for the compositor. You may be able to retrieve it using the "
"coredumpctl utility. For more information, see "
"<link "
"url='https://community.kde.org/Guidelines_and_HOWTOs/Debugging/How_to_create_useful_crash_reports#Retrieving_a_backtrace_using_coredumpctl'>the "
"KDE Community Wiki</"
"link>."));
ui.m_showReportInformationButton->setVisible(false); // Don't give access to the report, lest people file them manually.
if (!DrKonqi::crashedApplication()->hasBeenRestarted()) {
ui.m_restartAppOnFinish->setVisible(true);
}
emit finished(false /* don't enable back button - the user can't improve this result*/);
return;
}
BugReportAddress reportAddress = DrKonqi::crashedApplication()->bugReportAddress();
BacktraceParser::Usefulness use = DrKonqi::debuggerManager()->backtraceGenerator()->parser()->backtraceUsefulness();
......
/*
SPDX-FileCopyrightText: 2009-2010 George Kiagiadakis <kiagiadakis.george@gmail.com>
SPDX-FileCopyrightText: 2021 Harald Sitter <sitter@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
......@@ -118,6 +119,19 @@ QSet<QString> BacktraceParser::librariesWithMissingDebugSymbols() const
return d ? d->m_librariesWithMissingDebugSymbols : QSet<QString>();
}
bool BacktraceParser::hasCompositorCrashed() const
{
Q_D(const BacktraceParser);
// if there is no cached usefulness, the data calculation function has not run yet.
if (d && d->m_usefulness == InvalidUsefulness) {
const_cast<BacktraceParser *>(this)->calculateRatingData();
}
// if there is no d, the debugger has not run yet, so we don't know anything.
return d ? d->m_compositorCrashed : false;
}
void BacktraceParser::resetState()
{
// reset the state of the parser by getting a new instance of Private
......@@ -272,6 +286,10 @@ void BacktraceParser::calculateRatingData()
while (i.hasPrevious()) {
const BacktraceLine &line = i.previous();
if (!d->m_compositorCrashed && line.toString().contains(QLatin1String("The Wayland connection broke. Did the Wayland compositor die"))) {
d->m_compositorCrashed = true;
}
if (!i.hasPrevious() && line.rating() == BacktraceLine::MissingEverything) {
// Under some circumstances, the very first stack frame is invalid (ex, calling a function
// at an invalid address could result in a stack frame like "0x00000000 in ?? ()"),
......
/*
SPDX-FileCopyrightText: 2009-2010 George Kiagiadakis <kiagiadakis.george@gmail.com>
SPDX-FileCopyrightText: 2021 Harald Sitter <sitter@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
......@@ -61,6 +62,11 @@ public:
/*! Returns a list of libraries/executables that are missing debug symbols. */
virtual QSet<QString> librariesWithMissingDebugSymbols() const;
/*! Check if the crash is because of the client aborting after a compositor crash.
* https://bugs.kde.org/show_bug.cgi?id=431561
*/
bool hasCompositorCrashed() const;
QString informationLines() const;
private Q_SLOTS:
......
/*
SPDX-FileCopyrightText: 2009-2010 George Kiagiadakis <kiagiadakis.george@gmail.com>
SPDX-FileCopyrightText: 2021 Harald Sitter <sitter@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
......@@ -26,6 +27,7 @@ public:
QString m_simplifiedBacktrace;
QSet<QString> m_librariesWithMissingDebugSymbols;
BacktraceParser::Usefulness m_usefulness;
bool m_compositorCrashed = false;
};
#endif // BACKTRACEPARSER_P_H
/*
SPDX-FileCopyrightText: 2009 George Kiagiadakis <gkiagia@users.sourceforge.net>
SPDX-FileCopyrightText: 2021 Harald Sitter <sitter@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
......@@ -21,6 +22,7 @@ void BacktraceParserTest::fetchData(const QString &group)
QTest::addColumn<QString>("filename");
QTest::addColumn<QString>("result");
QTest::addColumn<QString>("debugger");
QTest::addColumn<bool>("compositorCrash");
m_settings.beginGroup(group);
QStringList keys = m_settings.allKeys();
......@@ -28,7 +30,8 @@ void BacktraceParserTest::fetchData(const QString &group)
foreach (const QString &key, keys) {
QTest::newRow(qPrintable(key)) << QString(DATA_DIR + QLatin1Char('/') + key) << m_settings.value(group + QLatin1Char('/') + key).toString()
<< m_settings.value(QStringLiteral("debugger/") + key).toString();
<< m_settings.value(QStringLiteral("debugger/") + key).toString()
<< m_settings.value(QStringLiteral("compositorCrash/") + key).toBool();
}
}
......@@ -104,4 +107,23 @@ void BacktraceParserTest::btParserBenchmark()
}
}
void BacktraceParserTest::btParserCompositorCrashTest_data()
{
fetchData(QStringLiteral("compositorCrash"));
}
void BacktraceParserTest::btParserCompositorCrashTest()
{
QFETCH(QString, filename);
QFETCH(QString, debugger);
QFETCH(bool, compositorCrash);
// parse
QSharedPointer<BacktraceParser> parser(BacktraceParser::newParser(debugger));
parser->connectToGenerator(m_generator);
m_generator->sendData(filename);
// compare
QCOMPARE(parser->hasCompositorCrashed(), compositorCrash);
}
QTEST_GUILESS_MAIN(BacktraceParserTest)
/*
SPDX-FileCopyrightText: 2009 George Kiagiadakis <gkiagia@users.sourceforge.net>
SPDX-FileCopyrightText: 2021 Harald Sitter <sitter@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
......@@ -24,6 +25,8 @@ private Q_SLOTS:
void btParserFunctionsTest();
void btParserBenchmark_data();
void btParserBenchmark();
void btParserCompositorCrashTest_data();
void btParserCompositorCrashTest();
private:
void fetchData(const QString &group);
......
......@@ -44,3 +44,8 @@ test_usefulfunctions4=gdb
test_usefulfunctions5=gdb
test_trailing_const=gdb
test_anon_namespace=gdb
test_compositorCrashBug431561=gdb
[compositorCrash]
test_a=false
test_compositorCrashBug431561=true
[Current thread is 0 (process 12545)]
Thread 7 (Thread 0x7ff99173f700 (LWP 15444)):
#0 0x00007ff996f33868 in qt_clock_gettime (ts=<optimized out>, clock=<optimized out>) at kernel/qelapsedtimer_unix.cpp:173
#1 do_gettime (frac=<optimized out>, sec=<optimized out>) at kernel/qelapsedtimer_unix.cpp:166
#2 qt_gettime () at kernel/qelapsedtimer_unix.cpp:175
#3 0x00007ff996f3211d in QTimerInfoList::updateCurrentTime (this=this@entry=0x7ff98c005130) at kernel/qtimerinfo_unix.cpp:91
#4 0x00007ff996f326f9 in QTimerInfoList::timerWait (this=0x7ff98c005130, tm=...) at kernel/qtimerinfo_unix.cpp:388
#5 0x00007ff996f33d16 in timerSourcePrepareHelper (timeout=0x7ff99173eae4, src=<optimized out>) at kernel/qeventdispatcher_glib.cpp:162
#6 timerSourcePrepare (source=<optimized out>, timeout=timeout@entry=0x7ff99173eae4) at kernel/qeventdispatcher_glib.cpp:166
#7 0x00007ff994c9f72f in g_main_context_prepare (context=context@entry=0x7ff98c000c20, priority=priority@entry=0x7ff99173eb70) at ../../../glib/gmain.c:3619
#8 0x00007ff994ca00db in g_main_context_iterate (context=context@entry=0x7ff98c000c20, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../../../glib/gmain.c:4027
#9 0x00007ff994ca02e3 in g_main_context_iteration (context=0x7ff98c000c20, may_block=may_block@entry=1) at ../../../glib/gmain.c:4108
#10 0x00007ff996f33fbb in QEventDispatcherGlib::processEvents (this=0x7ff98c000b60, flags=...) at kernel/qeventdispatcher_glib.cpp:425
#11 0x00007ff996ed81ab in QEventLoop::exec (this=this@entry=0x7ff99173ecb0, flags=..., flags@entry=...) at ../../include/QtCore/../../src/corelib/global/qflags.h:141
#12 0x00007ff996cf2a12 in QThread::exec (this=this@entry=0x7ff99800dd80 <(anonymous namespace)::Q_QGS__q_manager::innerFunction()::holder>) at ../../include/QtCore/../../src/corelib/global/qflags.h:121
#13 0x00007ff997f89f4b in QDBusConnectionManager::run (this=0x7ff99800dd80 <(anonymous namespace)::Q_QGS__q_manager::innerFunction()::holder>) at qdbusconnection.cpp:179
#14 0x00007ff996cf3bac in QThreadPrivate::start (arg=0x7ff99800dd80 <(anonymous namespace)::Q_QGS__q_manager::innerFunction()::holder>) at thread/qthread_unix.cpp:329
#15 0x00007ff99566d609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#16 0x00007ff99920d293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Thread 6 (Thread 0x7ff97bfff700 (LWP 15449)):
#0 g_mutex_unlock (mutex=0x7ff970000c20) at ../../../glib/gthread-posix.c:1493
#1 0x00007ff994c9fbd9 in g_main_context_check (context=context@entry=0x7ff970000c20, max_priority=2147483647, fds=fds@entry=0x7ff970004e60, n_fds=n_fds@entry=1) at ../../../glib/gmain.c:3878
#2 0x00007ff994ca0152 in g_main_context_iterate (context=context@entry=0x7ff970000c20, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../../../glib/gmain.c:4044
#3 0x00007ff994ca02e3 in g_main_context_iteration (context=0x7ff970000c20, may_block=may_block@entry=1) at ../../../glib/gmain.c:4108
#4 0x00007ff996f33fbb in QEventDispatcherGlib::processEvents (this=0x7ff970000b60, flags=...) at kernel/qeventdispatcher_glib.cpp:425
#5 0x00007ff996ed81ab in QEventLoop::exec (this=this@entry=0x7ff97bffece0, flags=..., flags@entry=...) at ../../include/QtCore/../../src/corelib/global/qflags.h:141
#6 0x00007ff996cf2a12 in QThread::exec (this=<optimized out>) at ../../include/QtCore/../../src/corelib/global/qflags.h:121
#7 0x00007ff996cf3bac in QThreadPrivate::start (arg=0x5564551e1dc0) at thread/qthread_unix.cpp:329
#8 0x00007ff99566d609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#9 0x00007ff99920d293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Thread 5 (Thread 0x7ff988bf2700 (LWP 15448)):
#0 futex_wait_cancelable (private=<optimized out>, expected=0, futex_word=0x556454f61818) at ../sysdeps/nptl/futex-internal.h:183
#1 __pthread_cond_wait_common (abstime=0x0, clockid=0, mutex=0x556454f617c8, cond=0x556454f617f0) at pthread_cond_wait.c:508
#2 __pthread_cond_wait (cond=0x556454f617f0, mutex=0x556454f617c8) at pthread_cond_wait.c:638
#3 0x00007ff98aaefe6b in ?? () from /usr/lib/x86_64-linux-gnu/dri/i965_dri.so
#4 0x00007ff98aaefa6b in ?? () from /usr/lib/x86_64-linux-gnu/dri/i965_dri.so
#5 0x00007ff99566d609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#6 0x00007ff99920d293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Thread 4 (Thread 0x7ff9893f3700 (LWP 15447)):
#0 futex_wait_cancelable (private=<optimized out>, expected=0, futex_word=0x556454f61818) at ../sysdeps/nptl/futex-internal.h:183
#1 __pthread_cond_wait_common (abstime=0x0, clockid=0, mutex=0x556454f617c8, cond=0x556454f617f0) at pthread_cond_wait.c:508
#2 __pthread_cond_wait (cond=0x556454f617f0, mutex=0x556454f617c8) at pthread_cond_wait.c:638
#3 0x00007ff98aaefe6b in ?? () from /usr/lib/x86_64-linux-gnu/dri/i965_dri.so
#4 0x00007ff98aaefa6b in ?? () from /usr/lib/x86_64-linux-gnu/dri/i965_dri.so
#5 0x00007ff99566d609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#6 0x00007ff99920d293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Thread 3 (Thread 0x7ff989bf4700 (LWP 15446)):
#0 futex_wait_cancelable (private=<optimized out>, expected=0, futex_word=0x556454f61818) at ../sysdeps/nptl/futex-internal.h:183
#1 __pthread_cond_wait_common (abstime=0x0, clockid=0, mutex=0x556454f617c8, cond=0x556454f617f0) at pthread_cond_wait.c:508
#2 __pthread_cond_wait (cond=0x556454f617f0, mutex=0x556454f617c8) at pthread_cond_wait.c:638
#3 0x00007ff98aaefe6b in ?? () from /usr/lib/x86_64-linux-gnu/dri/i965_dri.so
#4 0x00007ff98aaefa6b in ?? () from /usr/lib/x86_64-linux-gnu/dri/i965_dri.so
#5 0x00007ff99566d609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#6 0x00007ff99920d293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Thread 2 (Thread 0x7ff98a3f5700 (LWP 15445)):
#0 futex_wait_cancelable (private=<optimized out>, expected=0, futex_word=0x556454f61818) at ../sysdeps/nptl/futex-internal.h:183
#1 __pthread_cond_wait_common (abstime=0x0, clockid=0, mutex=0x556454f617c8, cond=0x556454f617f0) at pthread_cond_wait.c:508
#2 __pthread_cond_wait (cond=0x556454f617f0, mutex=0x556454f617c8) at pthread_cond_wait.c:638
#3 0x00007ff98aaefe6b in ?? () from /usr/lib/x86_64-linux-gnu/dri/i965_dri.so
#4 0x00007ff98aaefa6b in ?? () from /usr/lib/x86_64-linux-gnu/dri/i965_dri.so
#5 0x00007ff99566d609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#6 0x00007ff99920d293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Thread 1 (Thread 0x7ff99229a8c0 (LWP 15422)):
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1 0x00007ff998918f9b in KCrash::defaultCrashHandler (sig=6) at ./src/kcrash.cpp:577
#2 <signal handler called>
#3 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#4 0x00007ff999110859 in __GI_abort () at abort.c:79
#5 0x00007ff996cb8be7 in qt_message_fatal (context=..., message=<synthetic pointer>...) at global/qlogging.cpp:1914
#6 QMessageLogger::fatal (this=this@entry=0x7fffd70c5ba0, msg=msg@entry=0x7ff994ac00b8 "The Wayland connection broke. Did the Wayland compositor die?") at global/qlogging.cpp:893
#7 0x00007ff994a03d65 in QtWaylandClient::QWaylandDisplay::checkError (this=<optimized out>) at /usr/include/x86_64-linux-gnu/qt5/QtCore/qlogging.h:90
#8 QtWaylandClient::QWaylandDisplay::checkError (this=<optimized out>) at qwaylanddisplay.cpp:204
#9 0x00007ff994a1516c in QtWaylandClient::QWaylandDisplay::flushRequests (this=0x556454c2cac0) at qwaylanddisplay.cpp:222
#10 0x00007ff996f106f0 in doActivate<false> (sender=0x556454c53150, signal_index=3, argv=0x7fffd70c5d10) at ../../include/QtCore/../../src/corelib/kernel/qobjectdefs_impl.h:395
#11 0x00007ff996f09a87 in QMetaObject::activate (sender=sender@entry=0x556454c53150, m=m@entry=0x7ff997173b60 <QSocketNotifier::staticMetaObject>, local_signal_index=local_signal_index@entry=0, argv=argv@entry=0x7fffd70c5d10) at kernel/qobject.cpp:3946
#12 0x00007ff996f14733 in QSocketNotifier::activated (this=this@entry=0x556454c53150, _t1=..., _t2=<optimized out>, _t3=...) at .moc/moc_qsocketnotifier.cpp:178
#13 0x00007ff996f14ed3 in QSocketNotifier::event (this=0x556454c53150, e=0x7fffd70c5fe0) at kernel/qsocketnotifier.cpp:302
#14 0x00007ff9979b0dc3 in QApplicationPrivate::notify_helper (this=this@entry=0x556454c25d60, receiver=receiver@entry=0x556454c53150, e=e@entry=0x7fffd70c5fe0) at kernel/qapplication.cpp:3632
#15 0x00007ff9979b9bb8 in QApplication::notify (this=0x7fffd70c6320, receiver=0x556454c53150, e=0x7fffd70c5fe0) at kernel/qapplication.cpp:3156
#16 0x00007ff996ed969a in QCoreApplication::notifyInternal2 (receiver=0x556454c53150, event=0x7fffd70c5fe0) at ../../include/QtCore/5.15.2/QtCore/private/../../../../../src/corelib/thread/qthread_p.h:325
#17 0x00007ff996f34ba5 in socketNotifierSourceDispatch (source=0x556454c50ea0) at kernel/qeventdispatcher_glib.cpp:107
#18 0x00007ff994c9ffbd in g_main_dispatch (context=0x556454c5dad0) at ../../../glib/gmain.c:3309
#19 g_main_context_dispatch (context=context@entry=0x556454c5dad0) at ../../../glib/gmain.c:3974
#20 0x00007ff994ca0240 in g_main_context_iterate (context=context@entry=0x556454c5dad0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../../../glib/gmain.c:4047
#21 0x00007ff994ca02e3 in g_main_context_iteration (context=0x556454c5dad0, may_block=may_block@entry=1) at ../../../glib/gmain.c:4108
#22 0x00007ff996f33fa2 in QEventDispatcherGlib::processEvents (this=0x556454c56240, flags=...) at kernel/qeventdispatcher_glib.cpp:423
#23 0x00007ff996ed81ab in QEventLoop::exec (this=this@entry=0x7fffd70c61f0, flags=..., flags@entry=...) at ../../include/QtCore/../../src/corelib/global/qflags.h:141
#24 0x00007ff996ee0354 in QCoreApplication::exec () at ../../include/QtCore/../../src/corelib/global/qflags.h:121
#25 0x00007ff9972af1e0 in QGuiApplication::exec () at kernel/qguiapplication.cpp:1867
#26 0x00007ff9979b0d39 in QApplication::exec () at kernel/qapplication.cpp:2824
#27 0x00007ff999332192 in kdemain (argc=<optimized out>, argv=<optimized out>) at ./src/main.cpp:222
#28 0x00007ff9991120b3 in __libc_start_main (main=0x556454278060 <main>, argc=1, argv=0x7fffd70c64c8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffd70c64b8) at ../csu/libc-start.c:308
#29 0x000055645427809e in _start ()
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment