diff --git a/src/main.cpp b/src/main.cpp --- a/src/main.cpp +++ b/src/main.cpp @@ -62,141 +62,147 @@ } #endif - 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); - // Session management is not needed, do not even connect in order to survive longer than ksmserver. - unsetenv("SESSION_MANAGER"); - - KAboutData aboutData(QStringLiteral("drkonqi"), i18n("The KDE Crash Handler"), - QString::fromLatin1(version), i18n(description), - KAboutLicense::GPL, - i18n("(C) 2000-2018, The DrKonqi Authors")); - aboutData.addAuthor(i18nc("@info:credit","Hans Petter Bieker"), QString(), - QStringLiteral("bieker@kde.org")); - aboutData.addAuthor(i18nc("@info:credit","Dario Andres Rodriguez"), QString(), - QStringLiteral("andresbajotierra@gmail.com")); - aboutData.addAuthor(i18nc("@info:credit","George Kiagiadakis"), QString(), - QStringLiteral("gkiagia@users.sourceforge.net")); - aboutData.addAuthor(i18nc("@info:credit","A. L. Spehr"), QString(), - QStringLiteral("spehr@kde.org")); - qa.setWindowIcon(QIcon::fromTheme(QStringLiteral("tools-report-bug"), qa.windowIcon())); - qa.setDesktopFileName(QStringLiteral("org.kde.drkonqi")); - - QCommandLineParser parser; - aboutData.setupCommandLine(&parser); - - QCommandLineOption signalOption(QStringLiteral("signal"), i18nc("@info:shell","The signal that was caught"), QStringLiteral("number")); - QCommandLineOption appNameOption(QStringLiteral("appname"), i18nc("@info:shell"," of the program"), QStringLiteral("name")); - QCommandLineOption appPathOption(QStringLiteral("apppath"), i18nc("@info:shell"," to the executable"), QStringLiteral("path")); - QCommandLineOption appVersionOption(QStringLiteral("appversion"), i18nc("@info:shell","The of the program"), QStringLiteral("version")); - QCommandLineOption bugAddressOption(QStringLiteral("bugaddress"), i18nc("@info:shell","The bug
to use"), QStringLiteral("address")); - QCommandLineOption programNameOption(QStringLiteral("programname"), i18nc("@info:shell","Translated of the program"), QStringLiteral("name")); - QCommandLineOption pidOption(QStringLiteral("pid"), i18nc("@info:shell","The of the program"), QStringLiteral("pid")); - QCommandLineOption startupIdOption(QStringLiteral("startupid"), i18nc("@info:shell","Startup of the program"), QStringLiteral("id")); - QCommandLineOption kdeinitOption(QStringLiteral("kdeinit"), i18nc("@info:shell","The program was started by kdeinit")); - QCommandLineOption saferOption(QStringLiteral("safer"), i18nc("@info:shell","Disable arbitrary disk access")); - QCommandLineOption restartedOption(QStringLiteral("restarted"), i18nc("@info:shell","The program has already been restarted")); - QCommandLineOption keepRunningOption(QStringLiteral("keeprunning"), i18nc("@info:shell","Keep the program running and generate " - "the backtrace at startup")); - QCommandLineOption threadOption(QStringLiteral("thread"), i18nc("@info:shell","The of the failing thread"), QStringLiteral("threadid")); - QCommandLineOption dialogOption(QStringLiteral("dialog"), i18nc("@info:shell","Do not show a notification but launch the debug dialog directly")); - - parser.addOption(signalOption); - parser.addOption(appNameOption); - parser.addOption(appPathOption); - parser.addOption(appVersionOption); - parser.addOption(bugAddressOption); - parser.addOption(programNameOption); - parser.addOption(pidOption); - parser.addOption(startupIdOption); - parser.addOption(kdeinitOption); - parser.addOption(saferOption); - parser.addOption(restartedOption); - parser.addOption(keepRunningOption); - 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)); + int ret; + // Create the QApplication in its own scope to clean it up + // before SIGCONT is sent to the crashed application in DrKonqi::cleanup(). + // This is a workaround for https://bugs.freedesktop.org/show_bug.cgi?id=109777 + { + 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); + // Session management is not needed, do not even connect in order to survive longer than ksmserver. + unsetenv("SESSION_MANAGER"); + + KAboutData aboutData(QStringLiteral("drkonqi"), i18n("The KDE Crash Handler"), + QString::fromLatin1(version), i18n(description), + KAboutLicense::GPL, + i18n("(C) 2000-2018, The DrKonqi Authors")); + aboutData.addAuthor(i18nc("@info:credit","Hans Petter Bieker"), QString(), + QStringLiteral("bieker@kde.org")); + aboutData.addAuthor(i18nc("@info:credit","Dario Andres Rodriguez"), QString(), + QStringLiteral("andresbajotierra@gmail.com")); + aboutData.addAuthor(i18nc("@info:credit","George Kiagiadakis"), QString(), + QStringLiteral("gkiagia@users.sourceforge.net")); + aboutData.addAuthor(i18nc("@info:credit","A. L. Spehr"), QString(), + QStringLiteral("spehr@kde.org")); + qa.setWindowIcon(QIcon::fromTheme(QStringLiteral("tools-report-bug"), qa.windowIcon())); + qa.setDesktopFileName(QStringLiteral("org.kde.drkonqi")); + + QCommandLineParser parser; + aboutData.setupCommandLine(&parser); + + QCommandLineOption signalOption(QStringLiteral("signal"), i18nc("@info:shell","The signal that was caught"), QStringLiteral("number")); + QCommandLineOption appNameOption(QStringLiteral("appname"), i18nc("@info:shell"," of the program"), QStringLiteral("name")); + QCommandLineOption appPathOption(QStringLiteral("apppath"), i18nc("@info:shell"," to the executable"), QStringLiteral("path")); + QCommandLineOption appVersionOption(QStringLiteral("appversion"), i18nc("@info:shell","The of the program"), QStringLiteral("version")); + QCommandLineOption bugAddressOption(QStringLiteral("bugaddress"), i18nc("@info:shell","The bug
to use"), QStringLiteral("address")); + QCommandLineOption programNameOption(QStringLiteral("programname"), i18nc("@info:shell","Translated of the program"), QStringLiteral("name")); + QCommandLineOption pidOption(QStringLiteral("pid"), i18nc("@info:shell","The of the program"), QStringLiteral("pid")); + QCommandLineOption startupIdOption(QStringLiteral("startupid"), i18nc("@info:shell","Startup of the program"), QStringLiteral("id")); + QCommandLineOption kdeinitOption(QStringLiteral("kdeinit"), i18nc("@info:shell","The program was started by kdeinit")); + QCommandLineOption saferOption(QStringLiteral("safer"), i18nc("@info:shell","Disable arbitrary disk access")); + QCommandLineOption restartedOption(QStringLiteral("restarted"), i18nc("@info:shell","The program has already been restarted")); + QCommandLineOption keepRunningOption(QStringLiteral("keeprunning"), i18nc("@info:shell","Keep the program running and generate " + "the backtrace at startup")); + QCommandLineOption threadOption(QStringLiteral("thread"), i18nc("@info:shell","The of the failing thread"), QStringLiteral("threadid")); + QCommandLineOption dialogOption(QStringLiteral("dialog"), i18nc("@info:shell","Do not show a notification but launch the debug dialog directly")); + + parser.addOption(signalOption); + parser.addOption(appNameOption); + parser.addOption(appPathOption); + parser.addOption(appVersionOption); + parser.addOption(bugAddressOption); + parser.addOption(programNameOption); + parser.addOption(pidOption); + parser.addOption(startupIdOption); + parser.addOption(kdeinitOption); + parser.addOption(saferOption); + parser.addOption(restartedOption); + parser.addOption(keepRunningOption); + 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); - - DrKonqi::setSignal(parser.value(signalOption).toInt()); - DrKonqi::setAppName(parser.value(appNameOption)); - DrKonqi::setAppPath(parser.value(appPathOption)); - DrKonqi::setAppVersion(parser.value(appVersionOption)); - DrKonqi::setBugAddress(parser.value(bugAddressOption)); - DrKonqi::setProgramName(parser.value(programNameOption)); - DrKonqi::setPid(parser.value(pidOption).toInt()); - DrKonqi::setKdeinit(parser.isSet(kdeinitOption)); - DrKonqi::setSafer(parser.isSet(saferOption)); - DrKonqi::setRestarted(parser.isSet(restartedOption)); - DrKonqi::setKeepRunning(parser.isSet(keepRunningOption)); - DrKonqi::setThread(parser.value(threadOption).toInt()); - auto forceDialog = parser.isSet(dialogOption); + parser.process(qa); + aboutData.processCommandLine(&parser); + + DrKonqi::setSignal(parser.value(signalOption).toInt()); + DrKonqi::setAppName(parser.value(appNameOption)); + DrKonqi::setAppPath(parser.value(appPathOption)); + DrKonqi::setAppVersion(parser.value(appVersionOption)); + DrKonqi::setBugAddress(parser.value(bugAddressOption)); + DrKonqi::setProgramName(parser.value(programNameOption)); + DrKonqi::setPid(parser.value(pidOption).toInt()); + DrKonqi::setKdeinit(parser.isSet(kdeinitOption)); + DrKonqi::setSafer(parser.isSet(saferOption)); + DrKonqi::setRestarted(parser.isSet(restartedOption)); + DrKonqi::setKeepRunning(parser.isSet(keepRunningOption)); + DrKonqi::setThread(parser.value(threadOption).toInt()); + auto forceDialog = parser.isSet(dialogOption); #if HAVE_X11 - const QString startupId = parser.value(startupIdOption); - if (!startupId.isEmpty()) { - QX11Info::setNextStartupId(startupId.toUtf8()); - } + const QString startupId = parser.value(startupIdOption); + if (!startupId.isEmpty()) { + QX11Info::setNextStartupId(startupId.toUtf8()); + } #endif - if (!DrKonqi::init()) { - return 1; - } + if (!DrKonqi::init()) { + return 1; + } - qa.setQuitOnLastWindowClosed(false); + qa.setQuitOnLastWindowClosed(false); - auto openDrKonqiDialog = [&qa]{ - DrKonqiDialog *w = new DrKonqiDialog(); - QObject::connect(w, &DrKonqiDialog::rejected, &qa, &QApplication::quit); - w->show(); + auto openDrKonqiDialog = [&qa]{ + DrKonqiDialog *w = new DrKonqiDialog(); + QObject::connect(w, &DrKonqiDialog::rejected, &qa, &QApplication::quit); + w->show(); #ifdef Q_OS_MACOS - KWindowSystem::forceActiveWindow(w->winId()); + KWindowSystem::forceActiveWindow(w->winId()); #endif - }; - - bool restarted = parser.isSet(restartedOption); - - // if no notification service is running (eg. shell crashed, or other desktop environment) - // and we didn't auto-restart the app, open DrKonqi dialog instead of showing an SNI - // and emitting a desktop notification - if (forceDialog || (!restarted && !StatusNotifier::notificationServiceRegistered())) { - openDrKonqiDialog(); - } else { - StatusNotifier *statusNotifier = new StatusNotifier(); - if (!restarted) { - statusNotifier->notify(); + }; + + bool restarted = parser.isSet(restartedOption); + + // if no notification service is running (eg. shell crashed, or other desktop environment) + // and we didn't auto-restart the app, open DrKonqi dialog instead of showing an SNI + // and emitting a desktop notification + if (forceDialog || (!restarted && !StatusNotifier::notificationServiceRegistered())) { + openDrKonqiDialog(); + } else { + StatusNotifier *statusNotifier = new StatusNotifier(); + if (!restarted) { + statusNotifier->notify(); + } + QObject::connect(statusNotifier, &StatusNotifier::expired, &qa, &QApplication::quit); + QObject::connect(statusNotifier, &StatusNotifier::activated, openDrKonqiDialog); } - QObject::connect(statusNotifier, &StatusNotifier::expired, &qa, &QApplication::quit); - QObject::connect(statusNotifier, &StatusNotifier::activated, openDrKonqiDialog); - } - int ret = qa.exec(); + ret = qa.exec(); + } DrKonqi::cleanup(); return ret;