diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,11 +1,11 @@ cmake_minimum_required(VERSION 3.0) project(drkonqi) -set(PROJECT_VERSION "5.15.3") +set(PROJECT_VERSION "5.16.80") set(PROJECT_VERSION_MAJOR 5) -set(QT_MIN_VERSION "5.11.0") -set(KF5_MIN_VERSION "5.54.0") +set(QT_MIN_VERSION "5.12.0") +set(KF5_MIN_VERSION "5.58.0") find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE) @@ -67,14 +67,20 @@ # bfd header requires this to be defined INTERFACE_COMPILE_DEFINITIONS "PACKAGE;PACKAGE_VERSION" ) + find_path(BFD_INCLUDE_DIR bfd.h) + include_directories(${BFD_INCLUDE_DIR}) endif() include_directories("${CMAKE_CURRENT_BINARY_DIR}") add_definitions(-DQT_NO_NARROWING_CONVERSIONS_IN_CONNECT) add_subdirectory(src) -install( FILES drkonqi.categories DESTINATION ${KDE_INSTALL_CONFDIR} ) +if (${ECM_VERSION} STRGREATER "5.58.0") + install(FILES drkonqi.categories DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR}) +else() + install(FILES drkonqi.categories DESTINATION ${KDE_INSTALL_CONFDIR}) +endif() feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -34,6 +34,7 @@ crashedapplication.cpp debugger.cpp debuggerlaunchers.cpp + ptracer.cpp debuggermanager.cpp applicationdetailsexamples.cpp gdbhighlighter.cpp @@ -84,8 +85,6 @@ add_executable(drkonqi ${drkonqi_SRCS}) ecm_mark_nongui_executable(drkonqi) -target_compile_definitions(drkonqi PRIVATE -DPROJECT_VERSION="${PROJECT_VERSION}") - target_link_libraries(drkonqi KF5::I18n KF5::CoreAddons diff --git a/src/aboutbugreportingdialog.cpp b/src/aboutbugreportingdialog.cpp --- a/src/aboutbugreportingdialog.cpp +++ b/src/aboutbugreportingdialog.cpp @@ -194,7 +194,7 @@ xi18nc("@info/rich", "If you are interested in helping us to keep the KDE bug tracker system " "clean and useful, which allows the developers to be more focused on " "fixing the real issues, you are welcome to " - "join the BugSquad team.")); + "join the BugSquad team.")); m_textBrowser->setText(text); diff --git a/src/backtracewidget.h b/src/backtracewidget.h --- a/src/backtracewidget.h +++ b/src/backtracewidget.h @@ -58,6 +58,7 @@ DebugPackageInstaller * m_debugPackageInstaller = nullptr; void setAsLoading(); + void adjustWindowSize(); private Q_SLOTS: void loadData(); diff --git a/src/backtracewidget.cpp b/src/backtracewidget.cpp --- a/src/backtracewidget.cpp +++ b/src/backtracewidget.cpp @@ -142,6 +142,25 @@ ui.m_copyButton->setEnabled(false); ui.m_saveButton->setEnabled(false); + + adjustWindowSize(); +} + +void BacktraceWidget::adjustWindowSize() +{ + // We substantially change label content in-place so the window might need + // resizing to fit everything again. This should get called whenever label + // content is changed. + // We'll only increase our size but never shrink it. Shrinking would almost + // always screw with user expectation (e.g. button position or manually + // resized window). + // https://bugs.kde.org/show_bug.cgi?id=406748 + // https://bugs.kde.org/show_bug.cgi?id=337319 + const auto hint = window()->sizeHint(); + const auto size = window()->size(); + if (hint.width() > size.width() || hint.height() > size.height()) { + window()->adjustSize(); + } } //Force backtrace generation @@ -192,6 +211,8 @@ "click Reload.")); ui.m_installDebugButton->setVisible(false); ui.m_reloadBacktraceButton->setEnabled(true); + + adjustWindowSize(); } void BacktraceWidget::loadData() @@ -311,10 +332,7 @@ ui.m_reloadBacktraceButton->setEnabled(true); - // We substantially change label content, the window might need resizing to - // fit it all. - // https://bugs.kde.org/show_bug.cgi?id=337319 - window()->adjustSize(); + adjustWindowSize(); emit stateChanged(); } diff --git a/src/bugzillaintegration/reportassistantpages_base.cpp b/src/bugzillaintegration/reportassistantpages_base.cpp --- a/src/bugzillaintegration/reportassistantpages_base.cpp +++ b/src/bugzillaintegration/reportassistantpages_base.cpp @@ -246,7 +246,7 @@ } else { QUrl url(reportAddress); if (QUrl(reportAddress).isRelative()) { //Scheme is missing - url = QUrl(QString::fromLatin1("http://%1").arg(reportAddress)); + url = QUrl(QString::fromLatin1("https://%1").arg(reportAddress)); } QDesktopServices::openUrl(url); } diff --git a/src/bugzillaintegration/reportassistantpages_bugzilla_duplicates.cpp b/src/bugzillaintegration/reportassistantpages_bugzilla_duplicates.cpp --- a/src/bugzillaintegration/reportassistantpages_bugzilla_duplicates.cpp +++ b/src/bugzillaintegration/reportassistantpages_bugzilla_duplicates.cpp @@ -599,11 +599,6 @@ BugzillaReportInformationDialog::~BugzillaReportInformationDialog() { - disconnect(m_parent->bugzillaManager(), &BugzillaManager::bugReportFetched, - this, &BugzillaReportInformationDialog::bugFetchFinished); - disconnect(m_parent->bugzillaManager(), SIGNAL(bugReportError(QString,QObject*)), - this, SLOT(bugFetchError(QString,QObject*))); - KConfigGroup config(KSharedConfig::openConfig(), "BugzillaReportInformationDialog"); KWindowConfig::saveWindowSize(windowHandle(), config); } diff --git a/src/config-drkonqi.h.cmake b/src/config-drkonqi.h.cmake --- a/src/config-drkonqi.h.cmake +++ b/src/config-drkonqi.h.cmake @@ -1,6 +1,7 @@ #cmakedefine01 HAVE_STRSIGNAL #cmakedefine01 HAVE_UNAME #cmakedefine01 HAVE_X11 -#cmakedefine01 HAVE_XMLRPCCLIENT #define DEBUG_PACKAGE_INSTALLER_NAME "@DEBUG_PACKAGE_INSTALLER_NAME@" + +#define PROJECT_VERSION "@PROJECT_VERSION@" diff --git a/src/data/debuggers/external.mac/lldbrc b/src/data/debuggers/external.mac/lldbrc --- a/src/data/debuggers/external.mac/lldbrc +++ b/src/data/debuggers/external.mac/lldbrc @@ -2,14 +2,18 @@ Name=lldb Name[ca]=lldb Name[ca@valencia]=lldb +Name[da]=lldb Name[de]=lldb Name[en_GB]=lldb Name[es]=lldb +Name[eu]=lldb Name[fi]=lldb Name[fr]=lldb Name[gl]=lldb Name[id]=lldb Name[it]=lldb +Name[ko]=lldb +Name[lt]=lldb Name[nl]=lldb Name[nn]=lldb Name[pl]=lldb diff --git a/src/data/debuggers/external/cdbrc b/src/data/debuggers/external/cdbrc new file mode 100644 --- /dev/null +++ b/src/data/debuggers/external/cdbrc @@ -0,0 +1,33 @@ +[General] +Name=cdb +Name[ca]=cdb +Name[ca@valencia]=cdb +Name[da]=cdb +Name[de]=cdb +Name[en_GB]=cdb +Name[es]=cdb +Name[eu]=cdb +Name[fi]=cdb +Name[fr]=cdb +Name[gl]=cdb +Name[id]=cdb +Name[it]=cdb +Name[ko]=cdb +Name[lt]=cdb +Name[nl]=cdb +Name[nn]=cdb +Name[pl]=cdb +Name[pt]=cdb +Name[pt_BR]=cdb +Name[ru]=cdb +Name[sk]=cdb +Name[sv]=cdb +Name[uk]=cdb +Name[x-test]=xxcdbxx +Name[zh_CN]=cdb +Name[zh_TW]=cdb +TryExec=cdb +Backends=KCrash + +[KCrash] +Exec=konsole --nofork -e cdb.exe -p %pid -lines -c "~*kv; q" diff --git a/src/data/debuggers/external/lldbrc b/src/data/debuggers/external/lldbrc --- a/src/data/debuggers/external/lldbrc +++ b/src/data/debuggers/external/lldbrc @@ -2,14 +2,18 @@ Name=lldb Name[ca]=lldb Name[ca@valencia]=lldb +Name[da]=lldb Name[de]=lldb Name[en_GB]=lldb Name[es]=lldb +Name[eu]=lldb Name[fi]=lldb Name[fr]=lldb Name[gl]=lldb Name[id]=lldb Name[it]=lldb +Name[ko]=lldb +Name[lt]=lldb Name[nl]=lldb Name[nn]=lldb Name[pl]=lldb diff --git a/src/data/debuggers/internal/cdbrc b/src/data/debuggers/internal/cdbrc new file mode 100644 --- /dev/null +++ b/src/data/debuggers/internal/cdbrc @@ -0,0 +1,33 @@ +[General] +Name=cdb +Name[ca]=cdb +Name[ca@valencia]=cdb +Name[da]=cdb +Name[de]=cdb +Name[en_GB]=cdb +Name[es]=cdb +Name[eu]=cdb +Name[fi]=cdb +Name[fr]=cdb +Name[gl]=cdb +Name[id]=cdb +Name[it]=cdb +Name[ko]=cdb +Name[lt]=cdb +Name[nl]=cdb +Name[nn]=cdb +Name[pl]=cdb +Name[pt]=cdb +Name[pt_BR]=cdb +Name[ru]=cdb +Name[sk]=cdb +Name[sv]=cdb +Name[uk]=cdb +Name[x-test]=xxcdbxx +Name[zh_CN]=cdb +Name[zh_TW]=cdb +TryExec=cdb +Backends=KCrash + +[KCrash] +Exec=cdb.exe -p %pid -lines -c "~*kv; q" diff --git a/src/data/debuggers/internal/lldbrc b/src/data/debuggers/internal/lldbrc --- a/src/data/debuggers/internal/lldbrc +++ b/src/data/debuggers/internal/lldbrc @@ -2,14 +2,18 @@ Name=lldb Name[ca]=lldb Name[ca@valencia]=lldb +Name[da]=lldb Name[de]=lldb Name[en_GB]=lldb Name[es]=lldb +Name[eu]=lldb Name[fi]=lldb Name[fr]=lldb Name[gl]=lldb Name[id]=lldb Name[it]=lldb +Name[ko]=lldb +Name[lt]=lldb Name[nl]=lldb Name[nn]=lldb Name[pl]=lldb diff --git a/src/data/mappings b/src/data/mappings --- a/src/data/mappings +++ b/src/data/mappings @@ -26,6 +26,7 @@ #KDE Platform (KIO) kioclient=kio|general ktrash=kio|trash +kiod5=frameworks-kio|general #KDE Platform (Baloo) baloo_file=frameworks-baloo|Baloo File Daemon @@ -61,6 +62,7 @@ plasma-device=Active|General plasmashell=plasmashell|general plasma-discover=Discover|discover +org_kde_powerdevil=Powerdevil|general #KDE Plasma SDK (Plasmate) plasmaengineexplorer=plasmate|general @@ -74,6 +76,9 @@ kwinactive=kwin|general kwinactive_gles=kwin|general +#Powerdevil +org_kde_powerdevil=Powerdevil|general + #KDE Kontact (Akonadi) akonadi_archivemail_agent=Akonadi|Archive Mail Agent akonadi_benchmarker=Akonadi|general @@ -234,7 +239,7 @@ xulrunner-stub=unknown|general #--- -#This section relates a product groupt to a product +#This section relates a product group to a product #--- [ProductGroup] @@ -264,7 +269,7 @@ kspread=calligratables #--- -#This section describes several bugzilla products groups. +#This section describes several bugzilla product groups. #--- [BZGroups] diff --git a/src/debugger.cpp b/src/debugger.cpp --- a/src/debugger.cpp +++ b/src/debugger.cpp @@ -24,6 +24,7 @@ #include "crashedapplication.h" #include "drkonqi.h" +#include "drkonqi_debug.h" //static QList Debugger::availableInternalDebuggers(const QString & backend) @@ -45,7 +46,14 @@ bool Debugger::isInstalled() const { QString tryexec = tryExec(); - return !tryexec.isEmpty() && !QStandardPaths::findExecutable(tryexec).isEmpty(); + if(tryexec.isEmpty()) { + qCDebug(DRKONQI_LOG) << "tryExec of" << name() << "is empty!"; + return false; + } + + // Find for executable in PATH and in our application path + return !QStandardPaths::findExecutable(tryexec).isEmpty() + || !QStandardPaths::findExecutable(tryexec, {QCoreApplication::applicationDirPath()}).isEmpty(); } QString Debugger::name() const diff --git a/src/debuggerlaunchers.h b/src/debuggerlaunchers.h --- a/src/debuggerlaunchers.h +++ b/src/debuggerlaunchers.h @@ -78,14 +78,15 @@ { Q_OBJECT public: - explicit DBusInterfaceLauncher(const QString &name, DBusInterfaceAdaptor *parent = nullptr); + explicit DBusInterfaceLauncher(const QString &name, qint64 pid, DBusInterfaceAdaptor *parent = nullptr); QString name() const override; public Q_SLOTS: void start() override; private: QString m_name; + qint64 m_pid; }; class DBusInterfaceAdaptor : public QDBusAbstractAdaptor @@ -97,7 +98,7 @@ public Q_SLOTS: int pid(); - Q_NOREPLY void registerDebuggingApplication(const QString &name); + Q_NOREPLY void registerDebuggingApplication(const QString &name, qint64 pid = 0); Q_NOREPLY void debuggingFinished(const QString &name); Q_NOREPLY void debuggerClosed(const QString &name); diff --git a/src/debuggerlaunchers.cpp b/src/debuggerlaunchers.cpp --- a/src/debuggerlaunchers.cpp +++ b/src/debuggerlaunchers.cpp @@ -16,6 +16,7 @@ */ #include "debuggerlaunchers.h" +#include #include #include @@ -26,6 +27,8 @@ #include "drkonqi.h" #include "crashedapplication.h" +#include "ptracer.h" + DefaultDebuggerLauncher::DefaultDebuggerLauncher(const Debugger & debugger, DebuggerManager *parent) : AbstractDebuggerLauncher(parent), m_debugger(debugger) { @@ -51,6 +54,7 @@ emit starting(); int pid = KProcess::startDetached(KShell::splitArgs(str)); if ( pid > 0 ) { + setPtracer(pid, DrKonqi::pid()); m_monitor->startMonitoring(pid); } else { qCWarning(DRKONQI_LOG) << "Could not start debugger:" << name(); @@ -60,6 +64,7 @@ void DefaultDebuggerLauncher::onProcessFinished() { + setPtracer(QCoreApplication::applicationPid(), DrKonqi::pid()); emit finished(); } @@ -76,8 +81,8 @@ #endif -DBusInterfaceLauncher::DBusInterfaceLauncher(const QString &name, DBusInterfaceAdaptor *parent) - : AbstractDebuggerLauncher(parent), m_name(name) +DBusInterfaceLauncher::DBusInterfaceLauncher(const QString &name, qint64 pid, DBusInterfaceAdaptor *parent) + : AbstractDebuggerLauncher(parent), m_name(name), m_pid(pid) { } @@ -89,6 +94,9 @@ void DBusInterfaceLauncher::start() { emit starting(); + + setPtracer(m_pid, DrKonqi::pid()); + emit static_cast(parent())->acceptDebuggingApplication(m_name); } @@ -108,10 +116,10 @@ return DrKonqi::crashedApplication()->pid(); } -void DBusInterfaceAdaptor::registerDebuggingApplication(const QString &name) +void DBusInterfaceAdaptor::registerDebuggingApplication(const QString &name, qint64 pid) { if (!name.isEmpty() && !m_launchers.contains(name)) { - auto launcher = new DBusInterfaceLauncher(name, this); + auto launcher = new DBusInterfaceLauncher(name, pid, this); m_launchers.insert(name, launcher); static_cast(parent())->addDebugger(launcher, true); } @@ -121,6 +129,7 @@ { auto it = m_launchers.find(name); if (it != m_launchers.end()) { + setPtracer(QCoreApplication::applicationPid(), DrKonqi::pid()); emit it.value()->finished(); } } diff --git a/src/drkonqi.cpp b/src/drkonqi.cpp --- a/src/drkonqi.cpp +++ b/src/drkonqi.cpp @@ -200,10 +200,15 @@ return; } - KIO::FileCopyJob* job = KIO::file_copy(QUrl::fromLocalFile(tf.fileName()), fileUrl); + // QFileDialog was run with confirmOverwrite, so we can safely + // overwrite as necesssary. + KIO::FileCopyJob* job = KIO::file_copy(QUrl::fromLocalFile(tf.fileName()), + fileUrl, + -1, + KIO::DefaultFlags | KIO::Overwrite); KJobWidgets::setWindow(job, parent); if (!job->exec()) { - KMessageBox::sorry(parent, job->errorText()); + KMessageBox::sorry(parent, job->errorString()); } } } diff --git a/src/drkonqibackends.cpp b/src/drkonqibackends.cpp --- a/src/drkonqibackends.cpp +++ b/src/drkonqibackends.cpp @@ -167,11 +167,12 @@ #elif !defined(Q_OS_WIN) QString defaultDebuggerName = config.readEntry("Debugger", QStringLiteral("gdb")); #else - QString defaultDebuggerName = config.readEntry("Debugger", QStringLiteral("kdbgwin")); + QString defaultDebuggerName = config.readEntry("Debugger", QStringLiteral("cdb")); #endif Debugger firstKnownGoodDebugger, preferredDebugger; foreach (const Debugger & debugger, internalDebuggers) { + qCDebug(DRKONQI_LOG) << "Check debugger if" << debugger.name() << "is installed:" << debugger.isInstalled(); if (!firstKnownGoodDebugger.isValid() && debugger.isInstalled()) { firstKnownGoodDebugger = debugger; } @@ -235,5 +236,3 @@ Q_UNUSED(signal); ::kill(s_pid, SIGKILL); } - - diff --git a/src/drkonqidialog.cpp b/src/drkonqidialog.cpp --- a/src/drkonqidialog.cpp +++ b/src/drkonqidialog.cpp @@ -39,9 +39,7 @@ #include "debuggerlaunchers.h" #include "drkonqi_globals.h" #include "config-drkonqi.h" -#if HAVE_XMLRPCCLIENT - #include "bugzillaintegration/reportassistantdialog.h" -#endif +#include "bugzillaintegration/reportassistantdialog.h" static const char ABOUT_BUG_REPORTING_URL[] = "#aboutbugreporting"; static QString DRKONQI_REPORT_BUG_URL = KDE_BUGZILLA_URL + QStringLiteral("enter_bug.cgi?product=drkonqi&format=guided"); @@ -185,8 +183,7 @@ bool enableReportAssistant = !crashedApp->bugReportAddress().isEmpty() && crashedApp->fakeExecutableBaseName() != QLatin1String("drkonqi") && - !DrKonqi::isSafer() && - HAVE_XMLRPCCLIENT; + !DrKonqi::isSafer(); reportButton->setEnabled(enableReportAssistant); connect(reportButton, &QPushButton::clicked, this, &DrKonqiDialog::startBugReportAssistant); @@ -267,13 +264,11 @@ void DrKonqiDialog::startBugReportAssistant() { -#if HAVE_XMLRPCCLIENT ReportAssistantDialog * bugReportAssistant = new ReportAssistantDialog(); bugReportAssistant->show(); connect(bugReportAssistant, &QObject::destroyed, this, &DrKonqiDialog::reject); hide(); -#endif } void DrKonqiDialog::linkActivated(const QString& link) diff --git a/src/kdbgwin/CMakeLists.txt b/src/kdbgwin/CMakeLists.txt --- a/src/kdbgwin/CMakeLists.txt +++ b/src/kdbgwin/CMakeLists.txt @@ -3,8 +3,8 @@ set(kdbgwin_SRCS common.h main.cpp - process.h - process.cpp + kdbgwin_process.h + kdbgwin_process.cpp abstract_generator.h abstract_generator.cpp callbacks.h @@ -14,11 +14,11 @@ ${CMAKE_CURRENT_BINARY_DIR}/../drkonqi_debug.cpp ) -set(COMMON_LIBS dbghelp psapi shlwapi) +set(COMMON_LIBS dbghelp psapi shlwapi Qt5::Core) if ( MINGW ) add_executable(kdbgwin ${kdbgwin_SRCS} mingw_generator.h mingw_generator.cpp) - target_link_libraries(kdbgwin PRIVATE ${COMMON_LIBS} bfd iberty intl ZLIB::ZLIB Qt5::Core) + target_link_libraries(kdbgwin PRIVATE ${COMMON_LIBS} bfd iberty intl ZLIB::ZLIB) endif () if ( MSVC OR ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")) add_executable(kdbgwin ${kdbgwin_SRCS} msvc_generator.h msvc_generator.cpp) diff --git a/src/kdbgwin/abstract_generator.h b/src/kdbgwin/abstract_generator.h --- a/src/kdbgwin/abstract_generator.h +++ b/src/kdbgwin/abstract_generator.h @@ -26,7 +26,7 @@ #pragma once #include "common.h" -#include "process.h" +#include "kdbgwin_process.h" #include diff --git a/src/kdbgwin/process.h b/src/kdbgwin/kdbgwin_process.h rename from src/kdbgwin/process.h rename to src/kdbgwin/kdbgwin_process.h diff --git a/src/kdbgwin/process.cpp b/src/kdbgwin/kdbgwin_process.cpp rename from src/kdbgwin/process.cpp rename to src/kdbgwin/kdbgwin_process.cpp --- a/src/kdbgwin/process.cpp +++ b/src/kdbgwin/kdbgwin_process.cpp @@ -24,7 +24,7 @@ *****************************************************************/ #include "common.h" -#include "process.h" +#include "kdbgwin_process.h" Process::Process() : m_bValid(FALSE) diff --git a/src/kdbgwin/main.cpp b/src/kdbgwin/main.cpp --- a/src/kdbgwin/main.cpp +++ b/src/kdbgwin/main.cpp @@ -26,7 +26,7 @@ #include "msvc_generator.h" #include "mingw_generator.h" #include "outputters.h" -#include "process.h" +#include "kdbgwin_process.h" #include "common.h" #include diff --git a/src/kdbgwin/mingw_generator.cpp b/src/kdbgwin/mingw_generator.cpp --- a/src/kdbgwin/mingw_generator.cpp +++ b/src/kdbgwin/mingw_generator.cpp @@ -63,8 +63,8 @@ { QString modPath = GetModulePath(); bool existsSymbol = false; - TSymbolsMap::const_iterator i = m_symbolsMap.find(modPath); - if (i == m_symbolsMap.end()) + TSymbolsMap::const_iterator i = m_symbolsMap.constFind(modPath); + if (i == m_symbolsMap.cend()) { return; } @@ -133,7 +133,7 @@ QString symbolType; do { - bfd* abfd = bfd_openr(symbolFile.toLatin1(), NULL); + bfd* abfd = bfd_openr(symbolFile.toLatin1().data(), NULL); if (abfd == NULL) { symbolType = QString::fromLatin1("no symbols loaded"); diff --git a/src/kdbgwin/msvc_generator.cpp b/src/kdbgwin/msvc_generator.cpp --- a/src/kdbgwin/msvc_generator.cpp +++ b/src/kdbgwin/msvc_generator.cpp @@ -78,7 +78,7 @@ return QString::fromLatin1(DEFAULT_FILE); } - return QString(line.FileName); + return QString::fromLatin1(const_cast(line.FileName)); } int MsvcGenerator::GetLine() diff --git a/src/main.cpp b/src/main.cpp --- a/src/main.cpp +++ b/src/main.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #if HAVE_X11 @@ -42,6 +43,7 @@ #include #endif +#include "config-drkonqi.h" #include "drkonqi.h" #include "drkonqidialog.h" #include "statusnotifier.h" @@ -63,9 +65,6 @@ QApplication qa(argc, argv); qa.setAttribute(Qt::AA_UseHighDpiPixmaps, true); KLocalizedString::setApplicationDomain("drkonqi5"); - QCoreApplication::setApplicationName(QStringLiteral("drkonqi")); - QCoreApplication::setApplicationVersion(QString::fromLatin1(version)); - QCoreApplication::setOrganizationDomain(QStringLiteral("kde.org")); // Prevent KApplication from setting the crash handler. We will set it later... setenv("KDE_DEBUG", "true", 1); @@ -84,8 +83,8 @@ QStringLiteral("gkiagia@users.sourceforge.net")); aboutData.addAuthor(i18nc("@info:credit","A. L. Spehr"), QString(), QStringLiteral("spehr@kde.org")); + KAboutData::setApplicationData(aboutData); qa.setWindowIcon(QIcon::fromTheme(QStringLiteral("tools-report-bug"), qa.windowIcon())); - qa.setDesktopFileName(QStringLiteral("org.kde.drkonqi")); QCommandLineParser parser; aboutData.setupCommandLine(&parser); @@ -121,6 +120,24 @@ parser.addOption(threadOption); parser.addOption(dialogOption); + // Add all unknown options but make sure to print a warning. + // This enables older DrKonqi's to run by newer KCrash instances with + // possibly different/new options. + // KCrash can always send all options it knows to send and be sure that + // DrKonqi will not explode on them. If an option is not known here it's + // either too old or too new. + // + // To implement this smartly we'll ::parse all arguments, and then ::process + // them again once we have injected no-op options for all unknown ones. + // This allows ::process to still do common argument handling for --version + // as well as standard error handling. + if (!parser.parse(qa.arguments())) { + for (const QString &option : parser.unknownOptionNames()) { + qWarning() << "Unknown option" << option << " - ignoring it."; + parser.addOption(QCommandLineOption(option)); + } + } + parser.process(qa); aboutData.processCommandLine(&parser); diff --git a/src/org.kde.drkonqi.desktop.cmake b/src/org.kde.drkonqi.desktop.cmake --- a/src/org.kde.drkonqi.desktop.cmake +++ b/src/org.kde.drkonqi.desktop.cmake @@ -19,6 +19,7 @@ Name[id]=Dr Konqi Name[it]=Dr Konqi Name[ko]=Dr Konqi +Name[lt]=Dr. Konqi Name[nb]=Dr Konqi Name[nl]=Dr Konqi Name[nn]=Dr Konqi diff --git a/src/parser/CMakeLists.txt b/src/parser/CMakeLists.txt --- a/src/parser/CMakeLists.txt +++ b/src/parser/CMakeLists.txt @@ -4,6 +4,7 @@ backtraceparserkdbgwin.cpp backtraceparsernull.cpp backtraceparserlldb.cpp + backtraceparsercdb.cpp ) ecm_qt_declare_logging_category(BACKTRACEPARSER_SRCS HEADER drkonqi_parser_debug.h IDENTIFIER DRKONQI_PARSER_LOG CATEGORY_NAME org.kde.drkonqi.parser) diff --git a/src/parser/backtraceparser.cpp b/src/parser/backtraceparser.cpp --- a/src/parser/backtraceparser.cpp +++ b/src/parser/backtraceparser.cpp @@ -19,6 +19,7 @@ #include "backtraceparsergdb.h" #include "backtraceparserkdbgwin.h" #include "backtraceparserlldb.h" +#include "backtraceparsercdb.h" #include "backtraceparsernull.h" #include "drkonqi_parser_debug.h" #include @@ -34,6 +35,8 @@ return new BacktraceParserKdbgwin(parent); } else if (debuggerName == QLatin1String("lldb")) { return new BacktraceParserLldb(parent); + } else if (debuggerName == QLatin1String("cdb")) { + return new BacktraceParserCdb(parent); } else { return new BacktraceParserNull(parent); } diff --git a/src/parser/backtraceparsercdb.h b/src/parser/backtraceparsercdb.h new file mode 100644 --- /dev/null +++ b/src/parser/backtraceparsercdb.h @@ -0,0 +1,41 @@ +/* + Copyright (C) 2019 Patrick José Pereira + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#pragma once + +#include "backtraceparser.h" + +class BacktraceParserCdb : public BacktraceParser +{ + Q_OBJECT + Q_DECLARE_PRIVATE(BacktraceParser) + +public: + explicit BacktraceParserCdb(QObject *parent = nullptr); + +protected Q_SLOTS: + void newLine(const QString &lineStr) override; + +protected: + BacktraceParserPrivate *constructPrivate() const override; +}; + +class BacktraceLineCdb : public BacktraceLine +{ +public: + BacktraceLineCdb(const QString & line); +}; diff --git a/src/parser/backtraceparsercdb.cpp b/src/parser/backtraceparsercdb.cpp new file mode 100644 --- /dev/null +++ b/src/parser/backtraceparsercdb.cpp @@ -0,0 +1,44 @@ +/* + Copyright (C) 2019 Patrick José Pereira + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include "backtraceparsercdb.h" +#include "backtraceparser_p.h" + +BacktraceParserCdb::BacktraceParserCdb(QObject *parent) + : BacktraceParser(parent) +{ +} + +BacktraceParserPrivate *BacktraceParserCdb::constructPrivate() const +{ + BacktraceParserPrivate *d = BacktraceParser::constructPrivate(); + d->m_usefulness = MayBeUseful; + return d; +} + +void BacktraceParserCdb::newLine(const QString &lineStr) +{ + d_ptr->m_linesList.append(BacktraceLineCdb(lineStr)); +} + +BacktraceLineCdb::BacktraceLineCdb(const QString &line) + : BacktraceLine() +{ + d->m_line = line; + // We should do the faith jump to believe that cdb will provides useful information + d->m_rating = Good; +} \ No newline at end of file diff --git a/src/ptracer.h b/src/ptracer.h new file mode 100644 --- /dev/null +++ b/src/ptracer.h @@ -0,0 +1,25 @@ +/* + Copyright (C) 2019 Christoph Roick + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +#ifndef PTRACER_H +#define PTRACER_H + +#include + +/** On Linux, tell the process to allow the debugger to attach to it */ +void setPtracer(qint64 debuggerpid, qint64 debuggeepid); + +#endif diff --git a/src/ptracer.cpp b/src/ptracer.cpp new file mode 100644 --- /dev/null +++ b/src/ptracer.cpp @@ -0,0 +1,103 @@ +/* + Copyright (C) 2019 Christoph Roick + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +#include "ptracer.h" + +#ifdef Q_OS_LINUX + +#include "drkonqi_debug.h" + +#include +#include + +#include +#include +#include + +#include + +void setPtracer(qint64 debuggerpid, qint64 debuggeepid) +{ + + int sfd = socket(PF_UNIX, SOCK_STREAM, 0); + if (sfd < 0) { + qCWarning(DRKONQI_LOG) << "socket to set ptracer not accessible"; + return; + } + + static struct sockaddr_un server; + static socklen_t sl = sizeof(server); + server.sun_family = AF_UNIX; + const QString socketPath = + QStringLiteral("%1/kcrash_%2").arg(QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation)) + .arg(debuggeepid); + + if (socketPath.size() >= static_cast(sizeof(server.sun_path))) { + qCWarning(DRKONQI_LOG) << "socket path is too long"; + close(sfd); + return; + } + strcpy(server.sun_path, QFile::encodeName(socketPath).constData()); + + if (::connect(sfd, (struct sockaddr *)&server, sl) == 0) { + static const int msize = 21; // most digits in a 64bit int (+sign +'\0') + char msg[msize]; + sprintf(msg, "%lld", debuggerpid); + + int r, bytes = 0; + while (bytes < msize) { + r = write(sfd, msg + bytes, msize - bytes); + if (r > 0) + bytes += r; + else if (r == -1 && errno != EINTR) + break; + } + if (bytes == msize) { + struct pollfd fd; + fd.fd = sfd; + fd.events = POLLIN; + while ((r = poll(&fd, 1, 1000)) == -1 && errno == EINTR) {} + if (r > 0 && (fd.revents & POLLIN)) { + char rmsg[msize]; + bytes = 0; + while (bytes < msize) { + r = read(sfd, rmsg + bytes, msize - bytes); + if (r > 0) + bytes += r; + else if (r == -1 && errno != EINTR) + break; + } + if (bytes == msize && memcmp(msg, rmsg, msize) == 0) + qCInfo(DRKONQI_LOG) << "ptracer set to" << debuggerpid << "by debugged process"; + else + qCWarning(DRKONQI_LOG) << "debugged process did not acknowledge setting ptracer to" << debuggerpid; + close(sfd); + return; + } + } + } + + qCWarning(DRKONQI_LOG) << "unable to set ptracer to" << debuggerpid; + close(sfd); +} + +#else + +void setPtracer(qint64, qint64) +{ +} + +#endif diff --git a/src/statusnotifier.cpp b/src/statusnotifier.cpp --- a/src/statusnotifier.cpp +++ b/src/statusnotifier.cpp @@ -46,9 +46,7 @@ m_autoCloseTimer->setInterval(60000); m_autoCloseTimer->start(); connect(m_autoCloseTimer, &QTimer::timeout, this, &StatusNotifier::expired); - connect(this, &StatusNotifier::activated, this, [this] { - deleteLater(); - }); + connect(this, &StatusNotifier::activated, this, &StatusNotifier::deleteLater); KService::Ptr service = KService::serviceByStorageId(crashedApp->fakeExecutableBaseName()); if (service) { @@ -75,9 +73,7 @@ if (canBeRestarted(crashedApp)) { action = new QAction(QIcon::fromTheme(QStringLiteral("system-reboot")), i18n("&Restart Application"), nullptr); - connect(action, &QAction::triggered, this, [crashedApp] { - crashedApp->restart(); - }); + connect(action, &QAction::triggered, crashedApp, &CrashedApplication::restart); // once restarted successfully, disable restart option connect(crashedApp, &CrashedApplication::restarted, action, [action](bool success) { action->setEnabled(!success); diff --git a/src/tests/crashtest/crashtest.cpp b/src/tests/crashtest/crashtest.cpp --- a/src/tests/crashtest/crashtest.cpp +++ b/src/tests/crashtest/crashtest.cpp @@ -130,13 +130,17 @@ QCommandLineParser parser; parser.addOption(QCommandLineOption(QStringLiteral("autorestart"), i18n("Automatically restart"))); + parser.addOption(QCommandLineOption(QStringLiteral("kdeinit"), i18n("Start DrKonqi using kdeinit"))); parser.addPositionalArgument(QStringLiteral("type"), i18n("Type of crash."), QStringLiteral("crash|malloc|div0|assert|threads")); aboutData.setupCommandLine(&parser); parser.process(app); aboutData.processCommandLine(&parser); - //start drkonqi directly so that drkonqi's output goes to the console + // Start drkonqi directly by default so that drkonqi's output goes to the console. KCrash::CrashFlags flags = KCrash::AlwaysDirectly; + // This can be disabled to be able to test kcrash's real default behavior. + if (parser.isSet(QStringLiteral("kdeinit"))) + flags &= ~KCrash::AlwaysDirectly; if (parser.isSet(QStringLiteral("autorestart"))) flags |= KCrash::AutoRestart; KCrash::setFlags(flags);