Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package kcrash for openSUSE:Factory checked 
in at 2021-06-16 20:33:46
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/kcrash (Old)
 and      /work/SRC/openSUSE:Factory/.kcrash.new.32437 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "kcrash"

Wed Jun 16 20:33:46 2021 rev:92 rq:899721 version:5.83.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/kcrash/kcrash.changes    2021-05-10 
15:36:54.162151052 +0200
+++ /work/SRC/openSUSE:Factory/.kcrash.new.32437/kcrash.changes 2021-06-16 
20:35:15.483162890 +0200
@@ -1,0 +2,15 @@
+Sat Jun  5 11:58:38 UTC 2021 - Christophe Giboudeaux <[email protected]>
+
+- Update to 5.83.0
+  * New feature release
+  * For more details please see:
+  * https://kde.org/announcements/frameworks/5/5.83.0
+- Changes since 5.82.0:
+  * Use target_sources() to add sources to targets
+  * Add missing include <cerrno>
+  * write metadata to a cache file when applicable
+  * Bump required CMake version to 3.16
+  * Pass Bugzilla product name to DrKonqi when explicitly set in the app
+  * init rlp struct and don't cast rlim_t to int
+
+-------------------------------------------------------------------

Old:
----
  kcrash-5.82.0.tar.xz
  kcrash-5.82.0.tar.xz.sig

New:
----
  kcrash-5.83.0.tar.xz
  kcrash-5.83.0.tar.xz.sig

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ kcrash.spec ++++++
--- /var/tmp/diff_new_pack.NDBE3A/_old  2021-06-16 20:35:16.327164330 +0200
+++ /var/tmp/diff_new_pack.NDBE3A/_new  2021-06-16 20:35:16.331164337 +0200
@@ -17,7 +17,7 @@
 
 
 %define lname   libKF5Crash5
-%define _tar_path 5.82
+%define _tar_path 5.83
 # Full KF5 version (e.g. 5.33.0)
 %{!?_kf5_version: %global _kf5_version %{version}}
 # Last major and minor KF5 version (e.g. 5.33)
@@ -25,7 +25,7 @@
 # Only needed for the package signature condition
 %bcond_without lang
 Name:           kcrash
-Version:        5.82.0
+Version:        5.83.0
 Release:        0
 Summary:        An application crash handler
 License:        LGPL-2.1-or-later


++++++ kcrash-5.82.0.tar.xz -> kcrash-5.83.0.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcrash-5.82.0/.gitignore new/kcrash-5.83.0/.gitignore
--- old/kcrash-5.82.0/.gitignore        2021-05-01 11:39:00.000000000 +0200
+++ new/kcrash-5.83.0/.gitignore        2021-06-05 10:52:09.000000000 +0200
@@ -25,3 +25,4 @@
 .clangd
 .idea
 /cmake-build*
+.cache
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcrash-5.82.0/CMakeLists.txt 
new/kcrash-5.83.0/CMakeLists.txt
--- old/kcrash-5.82.0/CMakeLists.txt    2021-05-01 11:39:00.000000000 +0200
+++ new/kcrash-5.83.0/CMakeLists.txt    2021-06-05 10:52:09.000000000 +0200
@@ -1,11 +1,11 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.16)
 
-set(KF_VERSION "5.82.0") # handled by release scripts
-set(KF_DEP_VERSION "5.82.0") # handled by release scripts
+set(KF_VERSION "5.83.0") # handled by release scripts
+set(KF_DEP_VERSION "5.83.0") # handled by release scripts
 project(KCrash VERSION ${KF_VERSION})
 
 include(FeatureSummary)
-find_package(ECM 5.82.0  NO_MODULE)
+find_package(ECM 5.83.0  NO_MODULE)
 set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake 
Modules." URL "https://commits.kde.org/extra-cmake-modules";)
 feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND 
FATAL_ON_MISSING_REQUIRED_PACKAGES)
 
@@ -52,15 +52,8 @@
     KCRASH_CORE_PATTERN_RAISE
     "Raising signals to kernel core patterns (iff the pattern is a process). 
You may wish to not install drkonqi if this can cause a UI conflict.")
 
-if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/po)
-  include(ECMPoQmTools)
-  ecm_install_po_files_as_qm(po)
-endif()
-
-
 add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x050f00)
 add_definitions(-DKF_DISABLE_DEPRECATED_BEFORE_AND_AT=0x055100)
-add_definitions(-DQT_NO_FOREACH)
 add_subdirectory(src)
 if (BUILD_TESTING)
     add_subdirectory(autotests)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcrash-5.82.0/autotests/CMakeLists.txt 
new/kcrash-5.83.0/autotests/CMakeLists.txt
--- old/kcrash-5.82.0/autotests/CMakeLists.txt  2021-05-01 11:39:00.000000000 
+0200
+++ new/kcrash-5.83.0/autotests/CMakeLists.txt  2021-06-05 10:52:09.000000000 
+0200
@@ -38,3 +38,8 @@
   coreconfigtest.cpp
   LINK_LIBRARIES Qt5::Core Qt5::Test
 )
+
+ecm_add_tests(
+  metadatatest.cpp
+  LINK_LIBRARIES Qt5::Core Qt5::Test
+)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcrash-5.82.0/autotests/core_patterns/exec-apport 
new/kcrash-5.83.0/autotests/core_patterns/exec-apport
--- old/kcrash-5.82.0/autotests/core_patterns/exec-apport       1970-01-01 
01:00:00.000000000 +0100
+++ new/kcrash-5.83.0/autotests/core_patterns/exec-apport       2021-06-05 
10:52:09.000000000 +0200
@@ -0,0 +1 @@
+|/usr/share/apport/apport %p %s %c %d %P %E
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kcrash-5.82.0/autotests/core_patterns/exec-apport.license 
new/kcrash-5.83.0/autotests/core_patterns/exec-apport.license
--- old/kcrash-5.82.0/autotests/core_patterns/exec-apport.license       
1970-01-01 01:00:00.000000000 +0100
+++ new/kcrash-5.83.0/autotests/core_patterns/exec-apport.license       
2021-06-05 10:52:09.000000000 +0200
@@ -0,0 +1,2 @@
+SPDX-License-Identifier: CC0-1.0
+SPDX-FileCopyrightText: none
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcrash-5.82.0/autotests/coreconfigtest.cpp 
new/kcrash-5.83.0/autotests/coreconfigtest.cpp
--- old/kcrash-5.82.0/autotests/coreconfigtest.cpp      2021-05-01 
11:39:00.000000000 +0200
+++ new/kcrash-5.83.0/autotests/coreconfigtest.cpp      2021-06-05 
10:52:09.000000000 +0200
@@ -1,5 +1,5 @@
 /*
-    SPDX-FileCopyrightText: 2016 Harald Sitter <[email protected]>
+    SPDX-FileCopyrightText: 2016-2021 Harald Sitter <[email protected]>
 
     SPDX-License-Identifier: LGPL-2.0-or-later
 */
@@ -21,11 +21,24 @@
         KCrash::CoreConfig c(QFINDTESTDATA("core_patterns/exec"));
 #ifdef KCRASH_CORE_PATTERN_RAISE
         QCOMPARE(c.isProcess(), true);
+        QCOMPARE(c.isCoredumpd(), true);
 #else
         QCOMPARE(c.isProcess(), false);
+        QCOMPARE(c.isCoredumpd(), false);
 #endif
     }
 
+    void testExecNot()
+    {
+#ifndef KCRASH_CORE_PATTERN_RAISE
+        QSKIP("Not useful when opting out of re-raising.")
+#endif
+
+        KCrash::CoreConfig c(QFINDTESTDATA("core_patterns/exec-apport"));
+        QCOMPARE(c.isProcess(), true);
+        QCOMPARE(c.isCoredumpd(), false);
+    }
+
     void testNoFile()
     {
         KCrash::CoreConfig c("/meow/kitteh/meow");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcrash-5.82.0/autotests/metadatatest.cpp 
new/kcrash-5.83.0/autotests/metadatatest.cpp
--- old/kcrash-5.82.0/autotests/metadatatest.cpp        1970-01-01 
01:00:00.000000000 +0100
+++ new/kcrash-5.83.0/autotests/metadatatest.cpp        2021-06-05 
10:52:09.000000000 +0200
@@ -0,0 +1,63 @@
+/*
+    SPDX-License-Identifier: LGPL-2.0-or-later
+    SPDX-FileCopyrightText: 2021 Harald Sitter <[email protected]>
+*/
+
+#include <QTest>
+
+#include "../src/metadata.cpp"
+
+using namespace KCrash;
+
+class MetadataTest : public QObject
+{
+    Q_OBJECT
+private Q_SLOTS:
+    void testEverything()
+    {
+        QTemporaryDir tmpDir;
+        QVERIFY(tmpDir.isValid());
+
+        const QString iniFile = 
QStringLiteral("%1/foo.ini").arg(tmpDir.path());
+        MetadataWriter *writer = nullptr;
+#ifdef Q_OS_LINUX
+        MetadataINIWriter iniWriter(iniFile.toLocal8Bit());
+        writer = &iniWriter;
+#endif
+        Metadata data("BEFEHL", writer);
+        data.add("--ABC", "FOO");
+        data.addBool("--Meow");
+        data.close();
+        const int argc = data.argc;
+        QCOMPARE(argc, 4);
+        QCOMPARE(data.argv.at(0), QStringLiteral("BEFEHL")); // make sure we 
do stringy comparision
+        QCOMPARE(data.argv.at(1), QStringLiteral("--ABC"));
+        QCOMPARE(data.argv.at(2), QStringLiteral("FOO"));
+        QCOMPARE(data.argv.at(3), QStringLiteral("--Meow"));
+        QCOMPARE(data.argv.at(4), nullptr); // list should be null terminated
+
+#ifdef Q_OS_LINUX
+        QFile::exists(iniFile);
+        QFile ini(iniFile);
+        QVERIFY(ini.open(QFile::ReadOnly));
+        QCOMPARE(ini.readLine(), "[KCrash]\n");
+        QCOMPARE(ini.readLine(), "ABC=FOO\n");
+        QCOMPARE(ini.readLine(), "Meow=true\n");
+        QVERIFY(ini.atEnd()); // nothing after final newline
+#endif
+    }
+
+    void testNoFile()
+    {
+        // Doesn't explode without writer
+        Metadata data("BEFEHL", nullptr);
+        data.add("--ABC", "FOO");
+        data.close();
+        const int argc = data.argc;
+        QCOMPARE(argc, 3);
+    }
+};
+
+QTEST_MAIN(MetadataTest)
+
+#include "metadatatest.moc"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcrash-5.82.0/src/CMakeLists.txt 
new/kcrash-5.83.0/src/CMakeLists.txt
--- old/kcrash-5.82.0/src/CMakeLists.txt        2021-05-01 11:39:00.000000000 
+0200
+++ new/kcrash-5.83.0/src/CMakeLists.txt        2021-06-05 10:52:09.000000000 
+0200
@@ -1,8 +1,10 @@
+add_library(KF5Crash)
+add_library(KF5::Crash ALIAS KF5Crash)
 
-set(kcrash_SRCS
+target_sources(KF5Crash PRIVATE
   kcrash.cpp
   coreconfig.cpp
-  ${kcrash_QM_LOADER}
+  metadata.cpp
 )
 
 configure_file(
@@ -18,9 +20,7 @@
     EXPORT KCRASH
 )
 
-add_library(KF5Crash ${kcrash_SRCS})
 generate_export_header(KF5Crash BASE_NAME KCrash)
-add_library(KF5::Crash ALIAS KF5Crash)
 
 target_include_directories(KF5Crash INTERFACE 
"$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR_KF5}/KCrash>")
 
@@ -42,7 +42,7 @@
   target_include_directories(KF5Crash PRIVATE ${X11_X11_INCLUDE_PATH})
 endif()
 
-set_target_properties(KF5Crash PROPERTIES VERSION   ${KCrash_VERSION_STRING}
+set_target_properties(KF5Crash PROPERTIES VERSION   ${KCrash_VERSION}
                                           SOVERSION ${KCrash_SOVERSION}
                                           EXPORT_NAME Crash
 )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcrash-5.82.0/src/coreconfig.cpp 
new/kcrash-5.83.0/src/coreconfig.cpp
--- old/kcrash-5.82.0/src/coreconfig.cpp        2021-05-01 11:39:00.000000000 
+0200
+++ new/kcrash-5.83.0/src/coreconfig.cpp        2021-06-05 10:52:09.000000000 
+0200
@@ -1,5 +1,5 @@
 /*
-    SPDX-FileCopyrightText: 2016 Harald Sitter <[email protected]>
+    SPDX-FileCopyrightText: 2016-2021 Harald Sitter <[email protected]>
 
     SPDX-License-Identifier: LGPL-2.0-or-later
 */
@@ -9,7 +9,6 @@
 #include <QFile>
 
 #include <config-kcrash.h>
-
 namespace KCrash
 {
 CoreConfig::CoreConfig(const QString &path)
@@ -27,6 +26,10 @@
     }
     m_supported = true;
     m_process = first == '|';
+
+    if (file.readLine().contains(QByteArrayLiteral("systemd-coredump"))) {
+        m_coredumpd = true;
+    }
 }
 
 bool CoreConfig::isProcess() const
@@ -34,4 +37,9 @@
     return m_supported && m_process;
 }
 
+bool CoreConfig::isCoredumpd() const
+{
+    return m_coredumpd;
+}
+
 } // namespace KCrash
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcrash-5.82.0/src/coreconfig_p.h 
new/kcrash-5.83.0/src/coreconfig_p.h
--- old/kcrash-5.82.0/src/coreconfig_p.h        2021-05-01 11:39:00.000000000 
+0200
+++ new/kcrash-5.83.0/src/coreconfig_p.h        2021-06-05 10:52:09.000000000 
+0200
@@ -1,5 +1,5 @@
 /*
-    SPDX-FileCopyrightText: 2016 Harald Sitter <[email protected]>
+    SPDX-FileCopyrightText: 2016-2021 Harald Sitter <[email protected]>
 
     SPDX-License-Identifier: LGPL-2.0-or-later
 */
@@ -17,10 +17,13 @@
     CoreConfig(const QString &path = 
QStringLiteral("/proc/sys/kernel/core_pattern"));
 
     bool isProcess() const;
+    // should this need expansion please refactor to enum. could also store 
cmdline and compare in kcrash.cpp
+    bool isCoredumpd() const;
 
 private:
     bool m_supported = false;
     bool m_process = false;
+    bool m_coredumpd = false;
 };
 
 } // namespace KCrash
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcrash-5.82.0/src/kcrash.cpp 
new/kcrash-5.83.0/src/kcrash.cpp
--- old/kcrash-5.82.0/src/kcrash.cpp    2021-05-01 11:39:00.000000000 +0200
+++ new/kcrash-5.83.0/src/kcrash.cpp    2021-06-05 10:52:09.000000000 +0200
@@ -4,6 +4,7 @@
     SPDX-FileCopyrightText: 2000 Tom Braun <[email protected]>
     SPDX-FileCopyrightText: 2010 George Kiagiadakis 
<[email protected]>
     SPDX-FileCopyrightText: 2009 KDE e.V. <[email protected]>
+    SPDX-FileCopyrightText: 2021 Harald Sitter <[email protected]>
     SPDX-FileContributor: 2009 Adriaan de Groot <[email protected]>
 
     SPDX-License-Identifier: LGPL-2.0-or-later
@@ -39,6 +40,7 @@
 #include <memory>
 
 #include <QDebug>
+#include <QDir>
 #include <QFile>
 #include <QGuiApplication>
 #include <QLibraryInfo>
@@ -57,6 +59,7 @@
 #endif
 
 #include "coreconfig_p.h"
+#include "metadata_p.h"
 
 // Copy from klauncher_cmds
 typedef struct {
@@ -120,13 +123,15 @@
 
 static KCrash::HandlerType s_emergencySaveFunction = nullptr;
 static KCrash::HandlerType s_crashHandler = nullptr;
-static std::unique_ptr<char[]> s_appName;
-static std::unique_ptr<char[]> s_appPath;
+static std::unique_ptr<char[]> s_appFilePath; // this is the actual 
QCoreApplication::applicationFilePath
+static std::unique_ptr<char[]> s_appName; // the binary name (may be altered 
by the application)
+static std::unique_ptr<char[]> s_appPath; // the binary dir path (may be 
altered by the application)
 static Args s_autoRestartCommandLine;
 static std::unique_ptr<char[]> s_drkonqiPath;
 static KCrash::CrashFlags s_flags = KCrash::CrashFlags();
 static int s_launchDrKonqi = -1; // -1=initial value 0=disabled 1=enabled
 static int s_originalSignal = -1;
+static QByteArray s_metadataPath;
 
 static std::unique_ptr<char[]> s_kcrashErrorMessage;
 Q_GLOBAL_STATIC(KCrash::CoreConfig, s_coreConfig)
@@ -169,6 +174,18 @@
 }
 Q_COREAPP_STARTUP_FUNCTION(kcrashInitialize)
 
+static QStringList libexecPaths()
+{
+    // Static since we only need to evaluate once.
+    static QStringList list = 
QFile::decodeName(qgetenv("LIBEXEC_PATH")).split(QLatin1Char(':'), 
Qt::SkipEmptyParts) // env var is used first
+        + QStringList{
+            QCoreApplication::applicationDirPath(), // then look where our 
application binary is located
+            QLibraryInfo::location(QLibraryInfo::LibraryExecutablesPath), // 
look where libexec path is (can be set in qt.conf)
+            QFile::decodeName(KDE_INSTALL_FULL_LIBEXECDIR) // look at our 
installation location
+        };
+    return list;
+}
+
 namespace KCrash
 {
 void setApplicationFilePath(const QString &filePath);
@@ -179,6 +196,19 @@
 #endif
 }
 
+static bool shouldWriteMetadataToDisk()
+{
+#ifdef Q_OS_LINUX
+    // NB: The daemon being currently running must not be a condition here. If 
something crashes during logout
+    // the daemon may already be gone but we'll still want to deal with the 
crash on next login!
+    // Similar reasoning applies to not checking the presence of the launcher 
socket.
+    const bool drkonqiCoredumpHelper = 
!QStandardPaths::findExecutable(QStringLiteral("drkonqi-coredump-processor"), 
libexecPaths()).isEmpty();
+    return s_coreConfig()->isCoredumpd() && drkonqiCoredumpHelper && 
!qEnvironmentVariableIsSet("KCRASH_NO_METADATA");
+#else
+    return false;
+#endif
+}
+
 void KCrash::initialize()
 {
     if (s_launchDrKonqi == 0) { // disabled by the program itself
@@ -187,7 +217,8 @@
     const QStringList args = QCoreApplication::arguments();
     if (!qEnvironmentVariableIsSet("KDE_DEBUG") //
         && !qEnvironmentVariableIsSet("KCRASH_AUTO_RESTARTED") //
-        && !qEnvironmentVariableIntValue("RUNNING_UNDER_RR")) {
+        && !qEnvironmentVariableIntValue("RUNNING_UNDER_RR") //
+        && qEnvironmentVariableIntValue("KCRASH_DUMP_ONLY") == 0) {
         // enable drkonqi
         KCrash::setDrKonqiEnabled(true);
     } else {
@@ -196,18 +227,37 @@
     }
 
     if (QCoreApplication::instance()) {
-        
KCrash::setApplicationFilePath(QCoreApplication::applicationFilePath());
+        const QString path = QCoreApplication::applicationFilePath();
+        s_appFilePath.reset(qstrdup(qPrintable(path))); // This intentionally 
cannot be changed by the application!
+        KCrash::setApplicationFilePath(path);
     } else {
         qWarning() << "This process needs a QCoreApplication instance in order 
to use KCrash";
     }
 
 #ifdef Q_OS_LINUX
     // Create socket path to transfer ptrace scope and open connection
-    s_socketpath = QFile::encodeName(QStringLiteral("%1/kcrash_%2") //
-                                         
.arg(QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation))
-                                         .arg(getpid()));
+    s_socketpath = 
QFile::encodeName(QStringLiteral("%1/kcrash_%2").arg(QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation)).arg(getpid()));
 #endif
 
+    if (shouldWriteMetadataToDisk()) {
+        // We do not actively clean up metadata via KCrash but some other 
service. This potentially means we litter
+        // a lot -> put the metadata in a subdir.
+        const QString metadataDir = 
QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + 
QStringLiteral("/kcrash-metadata");
+        if (QDir().mkpath(metadataDir)) {
+            s_metadataPath = QFile::encodeName(metadataDir + 
QStringLiteral("/%1.ini").arg(QCoreApplication::applicationPid()));
+        }
+        if (!s_crashHandler) {
+            // Always enable the default handler. We cannot create the 
metadata ahead of time since we do not know
+            // when the application metadata is "complete".
+            // TODO: kf6 maybe change the way init works and have the users 
run it when their done with kaboutdata etc.?
+            //    the problem with delayed writing is that our crash handler 
(or any crash handler really) introduces a delay
+            //    in dumping and this in turn increases the risk of another 
stepping into a puddle (SEGV only runs on the
+            //    faulting thread; all other threads continue running!). 
therefore it'd be greatly preferred if we
+            //    were able to write the metadata during initial app setup 
instead of when a crash occurs
+            setCrashHandler(defaultCrashHandler);
+        }
+    } // empty s_metadataPath disables writing
+
     s_coreConfig(); // Initialize.
 }
 
@@ -300,15 +350,9 @@
     }
     s_launchDrKonqi = launchDrKonqi;
     if (s_launchDrKonqi && !s_drkonqiPath) {
-        // search paths
-        const QStringList paths =
-            QStringList() << 
QFile::decodeName(qgetenv("LIBEXEC_PATH")).split(QLatin1Char(':'), 
Qt::SkipEmptyParts) // env var is used first
-                          << QCoreApplication::applicationDirPath() // then 
look where our application binary is located
-                          << 
QLibraryInfo::location(QLibraryInfo::LibraryExecutablesPath) // look where 
libexec path is (can be set in qt.conf)
-                          << QFile::decodeName(KDE_INSTALL_FULL_LIBEXECDIR); 
// look at our installation location
-        const QString exec = 
QStandardPaths::findExecutable(QStringLiteral("drkonqi"), paths);
+        const QString exec = 
QStandardPaths::findExecutable(QStringLiteral("drkonqi"), libexecPaths());
         if (exec.isEmpty()) {
-            qCDebug(LOG_KCRASH) << "Could not find drkonqi in search paths:" 
<< paths;
+            qCDebug(LOG_KCRASH) << "Could not find drkonqi in search paths:" 
<< libexecPaths();
             s_launchDrKonqi = 0;
         } else {
             s_drkonqiPath.reset(qstrdup(qPrintable(exec)));
@@ -381,9 +425,9 @@
 static void closeAllFDs()
 {
     // Close all remaining file descriptors except for stdin/stdout/stderr
-    struct rlimit rlp;
+    struct rlimit rlp = {};
     getrlimit(RLIMIT_NOFILE, &rlp);
-    for (int i = 3; i < (int)rlp.rlim_cur; i++) {
+    for (rlim_t i = 3; i < rlp.rlim_cur; i++) {
         close(i);
     }
 }
@@ -419,142 +463,149 @@
         crashRecursionCounter++;
     }
 
-#if !defined(Q_OS_WIN) && !defined(Q_OS_OSX)
-    if (!(s_flags & KeepFDs)) {
-        // This tries to prevent problems where applications fail to release 
resources that drkonqi might need.
-        // Specifically this was introduced to ensure that an application that 
had grabbed the X11 cursor would
-        // forcefully have it removed upon crash to ensure it is ungrabbed by 
the time drkonqi makes an appearance.
-        // This is also the point in time when, for example, dbus services are 
lost. Closing the socket indicates
-        // to dbus-daemon that the process has disappeared and it will 
forcefully reclaim the registered service names.
-        closeAllFDs();
-    }
-#if HAVE_X11
-    else if (QX11Info::display()) {
-        close(ConnectionNumber(QX11Info::display()));
-    }
-#endif
-#endif
-
     if (crashRecursionCounter < 3) {
-#ifndef NDEBUG
-        fprintf(stderr, "KCrash: crashing... crashRecursionCounter = %d\n", 
crashRecursionCounter);
-        fprintf(stderr,
-                "KCrash: Application Name = %s path = %s pid = %lld\n",
-                s_appName ? s_appName.get() : "<unknown>",
-                s_appPath ? s_appPath.get() : "<unknown>",
-                QCoreApplication::applicationPid());
-        fprintf(stderr, "KCrash: Arguments: ");
-        for (int i = 0; i < s_autoRestartCommandLine.argc; ++i) {
-            fprintf(stderr, "%s ", s_autoRestartCommandLine.argv[i]);
-        }
-        fprintf(stderr, "\n");
-#else
-        fprintf(stderr, "KCrash: Application '%s' crashing...\n", s_appName ? 
s_appName.get() : "<unknown>");
-#endif
-
-        if (s_launchDrKonqi != 1) {
-            setCrashHandler(nullptr);
-#if !defined(Q_OS_WIN)
-            raise(sig); // dump core, or whatever is the default action for 
this signal.
-#endif
-            return;
-        }
-
         // If someone is telling me to stop while I'm already crashing, then I 
should resume crashing
         signal(SIGTERM, &crashOnSigTerm);
 
-        const char *argv[29]; // don't forget to update this
-        int i = 0;
-
-        // argument 0 has to be drkonqi
-        argv[i++] = s_drkonqiPath.get();
+        // NB: metadata writing ought to happen before closing FDs to reduce 
synchronization problems with dbus.
+        MetadataWriter *writer = nullptr;
+#ifdef Q_OS_LINUX
+        if (!s_metadataPath.isEmpty()) {
+            MetadataINIWriter ini(s_metadataPath);
+            // Add the canonical exe path so the coredump daemon has more data 
points to map metdata to journald entry.
+            ini.add("--exe", s_appFilePath.get(), 
MetadataWriter::BoolValue::No);
+            writer = &ini;
+        }
+#endif
+        // WARNING: do not forget to increase Metadata::argv's size when 
adding more potential arguments!
+        Metadata data(s_drkonqiPath.get(), writer);
 
         const QByteArray platformName = 
QGuiApplication::platformName().toUtf8();
         if (!platformName.isEmpty()) {
-            argv[i++] = "-platform";
-            argv[i++] = platformName.constData();
+            data.add("--platform", platformName.constData());
         }
 
 #if HAVE_X11
         if (platformName == QByteArrayLiteral("xcb")) {
             // start up on the correct display
-            argv[i++] = "-display";
+            char *display = nullptr;
             if (QX11Info::display()) {
-                argv[i++] = XDisplayString(QX11Info::display());
+                display = XDisplayString(QX11Info::display());
             } else {
-                argv[i++] = getenv("DISPLAY");
+                display = getenv("DISPLAY");
             }
+            data.add("--display", display);
         }
 #endif
 
-        argv[i++] = "--appname";
-        argv[i++] = s_appName ? s_appName.get() : "<unknown>";
+        data.add("--appname", s_appName ? s_appName.get() : "<unknown>");
 
         if (loadedByKdeinit) {
-            argv[i++] = "--kdeinit";
+            data.addBool("--kdeinit");
         }
 
         // only add apppath if it's not NULL
         if (s_appPath && s_appPath[0]) {
-            argv[i++] = "--apppath";
-            argv[i++] = s_appPath.get();
+            data.add("--apppath", s_appPath.get());
         }
 
         // signal number -- will never be NULL
         char sigtxt[10];
         sprintf(sigtxt, "%d", sig);
-        argv[i++] = "--signal";
-        argv[i++] = sigtxt;
+        data.add("--signal", sigtxt);
 
         char pidtxt[20];
         sprintf(pidtxt, "%lld", QCoreApplication::applicationPid());
-        argv[i++] = "--pid";
-        argv[i++] = pidtxt;
+        data.add("--pid", pidtxt);
 
         const KAboutData *about = KAboutData::applicationDataPointer();
         if (about) {
             if (about->internalVersion()) {
-                argv[i++] = "--appversion";
-                argv[i++] = about->internalVersion();
+                data.add("--appversion", about->internalVersion());
             }
 
             if (about->internalProgramName()) {
-                argv[i++] = "--programname";
-                argv[i++] = about->internalProgramName();
+                data.add("--programname", about->internalProgramName());
             }
 
             if (about->internalBugAddress()) {
-                argv[i++] = "--bugaddress";
-                argv[i++] = about->internalBugAddress();
+                data.add("--bugaddress", about->internalBugAddress());
+            }
+
+            if (about->internalProductName()) {
+                data.add("--productname", about->internalProductName());
             }
         }
 
         // make sure the constData() pointer remains valid when we call 
startProcess by making a copy
         QByteArray startupId = KStartupInfo::startupId();
         if (!startupId.isNull()) {
-            argv[i++] = "--startupid";
-            argv[i++] = startupId.constData();
+            data.add("--startupid", startupId.constData());
         }
 
         if (s_flags & SaferDialog) {
-            argv[i++] = "--safer";
+            data.addBool("--safer");
         }
 
         if ((s_flags & AutoRestart) && s_autoRestartCommandLine) {
-            argv[i++] = "--restarted"; // tell drkonqi if the app has been 
restarted
+            data.addBool("--restarted");
         }
 
 #if defined(Q_OS_WIN)
         char threadId[8] = {0};
         sprintf(threadId, "%d", GetCurrentThreadId());
-        argv[i++] = "--thread";
-        argv[i++] = threadId;
+        data.add("--thread", threadId);
+#endif
+
+        data.close();
+        const int argc = data.argc;
+        const char **argv = data.argv.data();
+
+#ifndef NDEBUG
+        fprintf(stderr, "KCrash: crashing... crashRecursionCounter = %d\n", 
crashRecursionCounter);
+        fprintf(stderr,
+                "KCrash: Application Name = %s path = %s pid = %lld\n",
+                s_appName ? s_appName.get() : "<unknown>",
+                s_appPath ? s_appPath.get() : "<unknown>",
+                QCoreApplication::applicationPid());
+        fprintf(stderr, "KCrash: Arguments: ");
+        for (int i = 0; i < s_autoRestartCommandLine.argc; ++i) {
+            fprintf(stderr, "%s ", s_autoRestartCommandLine.argv[i]);
+        }
+        fprintf(stderr, "\n");
+#else
+        fprintf(stderr, "KCrash: Application '%s' crashing...\n", s_appName ? 
s_appName.get() : "<unknown>");
+#endif
+
+#if !defined(Q_OS_WIN) && !defined(Q_OS_OSX)
+        if (!(s_flags & KeepFDs)) {
+            // This tries to prevent problems where applications fail to 
release resources that drkonqi might need.
+            // Specifically this was introduced to ensure that an application 
that had grabbed the X11 cursor would
+            // forcefully have it removed upon crash to ensure it is ungrabbed 
by the time drkonqi makes an appearance.
+            // This is also the point in time when, for example, dbus services 
are lost. Closing the socket indicates
+            // to dbus-daemon that the process has disappeared and it will 
forcefully reclaim the registered service names.
+            //
+            // Once we close our socket we lose potential dbus names and if we 
were running as a systemd service anchored to a name,
+            // the daemon may decide to jump at us with a TERM signal. We'll 
want to have finished the metadata by now and
+            // be near our tracing/raise().
+            closeAllFDs();
+        }
+#if HAVE_X11
+        else if (QX11Info::display()) {
+            close(ConnectionNumber(QX11Info::display()));
+        }
+#endif
 #endif
 
-        // NULL terminated list
-        argv[i] = nullptr;
+        if (s_launchDrKonqi != 1) {
+            setCrashHandler(nullptr);
+#if !defined(Q_OS_WIN)
+            raise(sig); // dump core, or whatever is the default action for 
this signal.
+#endif
+            return;
+        }
 
-        startProcess(i, argv, true);
+        startProcess(argc, argv, true);
     }
 
     if (crashRecursionCounter < 4) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcrash-5.82.0/src/metadata.cpp 
new/kcrash-5.83.0/src/metadata.cpp
--- old/kcrash-5.82.0/src/metadata.cpp  1970-01-01 01:00:00.000000000 +0100
+++ new/kcrash-5.83.0/src/metadata.cpp  2021-06-05 10:52:09.000000000 +0200
@@ -0,0 +1,111 @@
+/*
+    SPDX-License-Identifier: LGPL-2.0-or-later
+    SPDX-FileCopyrightText: 2021 Harald Sitter <[email protected]>
+*/
+
+#include "metadata_p.h"
+
+#include <QByteArray>
+#include <cerrno>
+
+#ifdef Q_OS_LINUX
+#include <cstring>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+namespace KCrash
+{
+#ifdef Q_OS_LINUX
+MetadataINIWriter::MetadataINIWriter(const QByteArray &path)
+    : MetadataWriter()
+    , fd(::open(path.constData(), O_WRONLY | O_CREAT | O_NONBLOCK | O_TRUNC | 
O_CLOEXEC, S_IRUSR | S_IWUSR))
+{
+    if (fd == -1) {
+        fprintf(stderr, "Failed to open metadata file: %s\n", strerror(errno));
+    } else {
+        const char *header = "[KCrash]\n";
+        write(fd, header, strlen(header));
+    }
+}
+
+void MetadataINIWriter::close()
+{
+    if (fd >= 0 && ::close(fd) == -1) {
+        fprintf(stderr, "Failed to close metadata file: %s\n", 
strerror(errno));
+    }
+}
+
+void MetadataINIWriter::add(const char *key, const char *value, BoolValue 
boolValue)
+{
+    Q_ASSERT(key);
+    Q_ASSERT(value);
+    Q_ASSERT(key[0] == '-' && key[1] == '-'); // well-formed '--' prefix. This 
is important. MetadataWriter presume this
+    Q_UNUSED(boolValue); // value is a bool string but we don't care, we 
always write the value anyway
+
+    if (fd < 0) {
+        return;
+    }
+    const int ret = snprintf(iniLine.data(), iniLine.max_size(), "%s=%s\n", 
key + 2 /** skip the leading -- */, value);
+    if (ret < 0) {
+        fprintf(stderr, "Failed to generate metadata line for '%s', '%s'\n", 
key, value);
+        return;
+    }
+    // Cannot be negative anymore.
+    const std::make_unsigned<decltype(ret)>::type lineLength = ret;
+    fprintf(stderr, "%d -- %s", lineLength, iniLine.data());
+    Q_ASSERT(lineLength <= iniLine.max_size()); // is not truncated41
+    write(fd, iniLine.data(), lineLength);
+}
+#endif
+
+Metadata::Metadata(const char *cmd, MetadataWriter *writer)
+    : MetadataWriter()
+    , m_writer(writer)
+{
+    // NB: cmd may be null! Just because we create metadata doesn't mean we'll 
execute drkonqi (we may only need the
+    // backing writers)
+    Q_ASSERT(argc == 0);
+    argv.at(argc++) = cmd;
+}
+
+void Metadata::add(const char *key, const char *value)
+{
+    add(key, value, BoolValue::No);
+}
+
+void Metadata::addBool(const char *key)
+{
+    add(key, "true", BoolValue::Yes);
+}
+
+void Metadata::close()
+{
+    // NULL terminated list
+    argv.at(argc) = nullptr;
+
+    if (m_writer) {
+        m_writer->close();
+    }
+}
+
+void Metadata::add(const char *key, const char *value, BoolValue boolValue)
+{
+    Q_ASSERT(key);
+    Q_ASSERT(value);
+    Q_ASSERT(key[0] == '-' && key[1] == '-'); // well-formed '--' prefix. This 
is important. MetadataWriter presume this
+    Q_ASSERT(argc < argv.max_size()); // argv has a static max size. guard 
against exhaustion
+
+    argv.at(argc++) = key;
+    if (!boolValue) {
+        argv.at(argc++) = value;
+    }
+
+    if (m_writer) {
+        m_writer->add(key, value, boolValue);
+    }
+}
+
+} // namespace KCrash
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcrash-5.82.0/src/metadata_p.h 
new/kcrash-5.83.0/src/metadata_p.h
--- old/kcrash-5.82.0/src/metadata_p.h  1970-01-01 01:00:00.000000000 +0100
+++ new/kcrash-5.83.0/src/metadata_p.h  2021-06-05 10:52:09.000000000 +0200
@@ -0,0 +1,83 @@
+/*
+    SPDX-License-Identifier: LGPL-2.0-or-later
+    SPDX-FileCopyrightText: 2021 Harald Sitter <[email protected]>
+*/
+
+#ifndef KCRASH_METADATA_H
+#define KCRASH_METADATA_H
+
+#include <QtGlobal>
+
+#include <array>
+
+class QByteArray;
+
+namespace KCrash
+{
+// A metadata writer interface.
+class MetadataWriter
+{
+public:
+    enum BoolValue { No = false, Yes = true };
+
+    virtual void add(const char *key, const char *value, BoolValue boolValue) 
= 0;
+    virtual void close() = 0;
+
+protected:
+    MetadataWriter() = default;
+    virtual ~MetadataWriter() = default;
+
+private:
+    Q_DISABLE_COPY_MOVE(MetadataWriter)
+};
+
+#ifdef Q_OS_LINUX
+// This writes the metdata file. Only really useful on Linux for now as this 
needs
+// cleanup by a helper daemon later. Also, this is only ever useful when 
coredump is in use.
+class MetadataINIWriter : public MetadataWriter
+{
+public:
+    explicit MetadataINIWriter(const QByteArray &path);
+    ~MetadataINIWriter() override = default;
+
+    void add(const char *key, const char *value, BoolValue boolValue) override;
+    void close() override;
+
+private:
+    int fd = -1;
+    std::array<char, 1024> iniLine{}; // arbitrary max size
+
+    Q_DISABLE_COPY_MOVE(MetadataINIWriter)
+};
+#endif
+
+// Compile the crash metadata. These are the primary ARGV metadata, but 
additional
+// metadata writers may be added behind it to (e.g.) write the data to a file 
as well.
+//   man 7 signal-safety
+class Metadata : public MetadataWriter
+{
+public:
+    Metadata(const char *cmd, MetadataWriter *writer);
+    ~Metadata() override = default;
+
+    void add(const char *key, const char *value);
+    void addBool(const char *key);
+
+    // Also closes the backing writer.
+    void close() override;
+
+    std::array<const char *, 31> argv{};
+    std::size_t argc = 0;
+
+private:
+    void add(const char *key, const char *value, BoolValue boolValue) override;
+
+    // Obviously if we should ever need more writers, refactor to 
std::initializer_list or something similar.
+    MetadataWriter *m_writer = nullptr;
+
+    Q_DISABLE_COPY_MOVE(Metadata)
+};
+
+} // namespace KCrash
+
+#endif // KCRASH_METADATA_H

Reply via email to