Hello community,

here is the log from the commit of package kcrash for openSUSE:Factory checked 
in at 2019-02-14 14:24:24
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/kcrash (Old)
 and      /work/SRC/openSUSE:Factory/.kcrash.new.28833 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "kcrash"

Thu Feb 14 14:24:24 2019 rev:63 rq:674226 version:5.55.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/kcrash/kcrash.changes    2019-01-21 
10:19:09.374147274 +0100
+++ /work/SRC/openSUSE:Factory/.kcrash.new.28833/kcrash.changes 2019-02-14 
14:24:26.299900619 +0100
@@ -1,0 +2,12 @@
+Sun Feb 10 22:03:03 UTC 2019 - [email protected]
+
+- Update to 5.55.0
+  * New feature release
+  * For more details please see:
+  * https://www.kde.org/announcements/kde-frameworks-5.55.0.php
+- Changes since 5.54.0:
+  * Comment why changing the ptracer is required
+  * [KCrash] Establish socket to allow change of ptracer
+  * Fix out-of-bounds assert while running unittests with argv==nullptr.
+
+-------------------------------------------------------------------
@@ -19,0 +32,5 @@
+
+-------------------------------------------------------------------
+Mon Nov 12 14:13:00 UTC 2018 - Jan Engelhardt <[email protected]>
+
+- Use noun phrase in summaries.

Old:
----
  kcrash-5.54.0.tar.xz

New:
----
  kcrash-5.55.0.tar.xz

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

Other differences:
------------------
++++++ kcrash.spec ++++++
--- /var/tmp/diff_new_pack.swQvpz/_old  2019-02-14 14:24:27.695899961 +0100
+++ /var/tmp/diff_new_pack.swQvpz/_new  2019-02-14 14:24:27.695899961 +0100
@@ -17,15 +17,15 @@
 
 
 %define lname   libKF5Crash5
-%define _tar_path 5.54
+%define _tar_path 5.55
 # Full KF5 version (e.g. 5.33.0)
 %{!?_kf5_version: %global _kf5_version %{version}}
 # Last major and minor KF5 version (e.g. 5.33)
 %{!?_kf5_bugfix_version: %define _kf5_bugfix_version %(echo %{_kf5_version} | 
awk -F. '{print $1"."$2}')}
 Name:           kcrash
-Version:        5.54.0
+Version:        5.55.0
 Release:        0
-Summary:        Gracefull handling of application crashes
+Summary:        An application crash handler
 License:        LGPL-2.1-or-later
 Group:          System/GUI/KDE
 URL:            https://www.kde.org
@@ -47,7 +47,7 @@
 KCrash provides support for intercepting and handling application crashes.
 
 %package -n %{lname}
-Summary:        Gracefull handling of application crashes
+Summary:        An application crash handler
 Group:          System/GUI/KDE
 Recommends:     drkonqi5
 
@@ -55,7 +55,7 @@
 KCrash provides support for intercepting and handling application crashes.
 
 %package devel
-Summary:        Gracefull handling of application crashes: Build Environment
+Summary:        Build environment for the KCrash application crash handler
 Group:          Development/Libraries/KDE
 Requires:       %{lname} = %{version}
 Requires:       extra-cmake-modules

++++++ kcrash-5.54.0.tar.xz -> kcrash-5.55.0.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcrash-5.54.0/CMakeLists.txt 
new/kcrash-5.55.0/CMakeLists.txt
--- old/kcrash-5.54.0/CMakeLists.txt    2019-01-04 22:41:32.000000000 +0100
+++ new/kcrash-5.55.0/CMakeLists.txt    2019-02-02 18:20:25.000000000 +0100
@@ -1,17 +1,17 @@
 cmake_minimum_required(VERSION 3.5)
 
-set(KF5_VERSION "5.54.0") # handled by release scripts
-set(KF5_DEP_VERSION "5.54.0") # handled by release scripts
+set(KF5_VERSION "5.55.0") # handled by release scripts
+set(KF5_DEP_VERSION "5.55.0") # handled by release scripts
 project(KCrash VERSION ${KF5_VERSION})
 
 include(FeatureSummary)
-find_package(ECM 5.54.0  NO_MODULE)
+find_package(ECM 5.55.0  NO_MODULE)
 set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake 
Modules." URL 
"https://projects.kde.org/projects/kdesupport/extra-cmake-modules";)
 feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND 
FATAL_ON_MISSING_REQUIRED_PACKAGES)
 
 set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR})
 
-set(REQUIRED_QT_VERSION 5.9.0)
+set(REQUIRED_QT_VERSION 5.10.0)
 find_package(Qt5 ${REQUIRED_QT_VERSION} CONFIG REQUIRED Core)
 include(KDEInstallDirs)
 include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcrash-5.54.0/src/kcrash.cpp 
new/kcrash-5.55.0/src/kcrash.cpp
--- old/kcrash-5.54.0/src/kcrash.cpp    2019-01-04 22:41:32.000000000 +0100
+++ new/kcrash-5.55.0/src/kcrash.cpp    2019-02-02 18:20:25.000000000 +0100
@@ -40,6 +40,7 @@
 #include <qt_windows.h>
 #endif
 #ifdef Q_OS_LINUX
+#include <sys/poll.h>
 #include <sys/prctl.h>
 #endif
 
@@ -218,14 +219,16 @@
     s_autoRestartCommand = qstrdup(QFile::encodeName(filePath).constData());
 
     QStringList args = QCoreApplication::arguments();
-    args[0] = filePath; // replace argv[0] with full path above
-    delete[] s_autoRestartCommandLine;
-    s_autoRestartArgc = args.count();
-    s_autoRestartCommandLine = new char *[args.count() + 1];
-    for (int i = 0; i < args.count(); ++i) {
-        s_autoRestartCommandLine[i] = 
qstrdup(QFile::encodeName(args.at(i)).constData());
+    if (!args.isEmpty()) { // edge case: tst_QX11Info::startupId does 
QApplication app(argc, nullptr)...
+        args[0] = filePath; // replace argv[0] with full path above
+        delete[] s_autoRestartCommandLine;
+        s_autoRestartArgc = args.count();
+        s_autoRestartCommandLine = new char *[args.count() + 1];
+        for (int i = 0; i < args.count(); ++i) {
+            s_autoRestartCommandLine[i] = 
qstrdup(QFile::encodeName(args.at(i)).constData());
+        }
+        s_autoRestartCommandLine[args.count()] = nullptr;
     }
-    s_autoRestartCommandLine[args.count()] = nullptr;
 }
 
 void KCrash::setDrKonqiEnabled(bool enabled)
@@ -616,6 +619,11 @@
 static int read_socket(int sock, char *buffer, int len);
 static int openSocket();
 
+#ifdef Q_OS_LINUX
+static int openDrKonqiSocket(const QByteArray &socketpath);
+static int pollDrKonqiSocket(pid_t pid, int sockfd);
+#endif
+
 void KCrash::startProcess(int argc, const char *argv[], bool waitAndExit)
 {
     bool startDirectly = true;
@@ -644,24 +652,50 @@
 
     if (pid > 0 && waitAndExit) {
         // Seems we made it....
-        alarm(0); //stop the pending alarm that was set at the top of the 
defaultCrashHandler
+        alarm(0); // Stop the pending alarm that was set at the top of the 
defaultCrashHandler
 
+        bool running = true;
         // Wait forever until the started process exits. This code path is 
executed
-        // when launching drkonqi. Note that drkonqi will stop this process in 
the meantime.
-        if (directly) {
-            //if the process was started directly, use waitpid(), as it's a 
child...
-            while (waitpid(-1, nullptr, 0) != pid) {}
-        } else {
+        // when launching drkonqi. Note that DrKonqi will SIGSTOP this process 
in the meantime
+        // and only send SIGCONT when it is about to attach a debugger.
 #ifdef Q_OS_LINUX
-            // Declare the process that will be debugging the crashed KDE app 
(#245529)
+        // Declare the process that will be debugging the crashed KDE app 
(#245529).
+        // For now that will be DrKonqi, which may ask to transfer the ptrace 
scope to
+        // a debugger it is not an ancestor of (because it was started via 
kdeinit or
+        // KProcess::startDetached()) using a socket.
 #ifndef PR_SET_PTRACER
 # define PR_SET_PTRACER 0x59616d61
 #endif
-            prctl(PR_SET_PTRACER, pid, 0, 0, 0);
+        prctl(PR_SET_PTRACER, pid, 0, 0, 0);
+
+        // Create socket path to transfer ptrace scope and open connection
+        const QByteArray socketpath = QFile::encodeName(
+            
QStringLiteral("%1/kcrash_%2").arg(QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation))
+                                          .arg(getpid()));
+        int sockfd = openDrKonqiSocket(socketpath);
+
+        if (sockfd >= 0) {
+            // Wait while DrKonqi is running and the socket connection exists
+            if (directly) {
+                // If the process was started directly, use waitpid(), as it's 
a child...
+                while ((running = waitpid(pid, nullptr, WNOHANG) != pid) && 
pollDrKonqiSocket(pid, sockfd) >= 0) {}
+            } else {
+                // ... else poll its status using kill()
+                while ((running = kill(pid, 0) >= 0) && pollDrKonqiSocket(pid, 
sockfd) >= 0) {}
+            }
+            close(sockfd);
+            unlink(socketpath.constData());
+        }
 #endif
-            //...else poll its status using kill()
-            while (kill(pid, 0) >= 0) {
-                sleep(1);
+        if (running) {
+            if (directly) {
+                // If the process was started directly, use waitpid(), as it's 
a child...
+                while (waitpid(pid, nullptr, 0) != pid) {}
+            } else {
+                // ... else poll its status using kill()
+                while (kill(pid, 0) >= 0) {
+                    sleep(1);
+                }
             }
         }
         if (!s_coreConfig->isProcess()) {
@@ -832,4 +866,90 @@
     return s;
 }
 
+#ifdef Q_OS_LINUX
+
+static int openDrKonqiSocket(const QByteArray &socketpath)
+{
+    int sockfd = socket(PF_UNIX, SOCK_STREAM, 0);
+    if (sockfd < 0) {
+        perror("Warning: socket() for communication with DrKonqi failed");
+        return -1;
+    }
+
+    struct sockaddr_un drkonqi_server;
+    drkonqi_server.sun_family = AF_UNIX;
+
+    if (socketpath.size() >= 
static_cast<int>(sizeof(drkonqi_server.sun_path))) {
+        fprintf(stderr, "Warning: socket path is too long\n");
+        close(sockfd);
+        return -1;
+    }
+    strcpy(drkonqi_server.sun_path, socketpath.constData());
+
+    unlink(drkonqi_server.sun_path); // remove potential stale socket
+    if (bind(sockfd, (struct sockaddr *)&drkonqi_server, 
sizeof(drkonqi_server)) < 0) {
+        perror("Warning: bind() for communication with DrKonqi failed");
+        close(sockfd);
+        unlink(drkonqi_server.sun_path);
+        return -1;
+    }
+
+    listen(sockfd, 1);
+
+    return sockfd;
+}
+
+static int pollDrKonqiSocket(pid_t pid, int sockfd)
+{
+    struct pollfd fd;
+    fd.fd = sockfd;
+    fd.events = POLLIN;
+    int r;
+    do {
+        r = poll(&fd, 1, 1000); // wait for 1 second for a request by DrKonqi
+    } while (r == -1 && errno == EINTR);
+    // only continue if POLLIN event returned
+    if (r == 0) // timeout
+        return 0;
+    else if (r == -1 || !(fd.revents & POLLIN)) // some error
+        return -1;
+
+    static struct sockaddr_un drkonqi_client;
+    static socklen_t cllength = sizeof(drkonqi_client);
+    int clsockfd;
+    do {
+        clsockfd = accept(sockfd, (struct sockaddr *)&drkonqi_client, 
&cllength);
+    } while (clsockfd == -1 && errno == EINTR);
+    if (clsockfd < 0)
+        return -1;
+
+    // check whether the message is coming from DrKonqi
+    static struct ucred ucred;
+    static socklen_t credlen = sizeof(struct ucred);
+    if (getsockopt(clsockfd, SOL_SOCKET, SO_PEERCRED, &ucred, &credlen) < 0)
+        return -1;
+
+    if (ucred.pid != pid) {
+        fprintf(stderr, "Warning: peer pid does not match DrKonqi pid\n");
+        return -1;
+    }
+
+    // read PID to change ptrace scope
+    static const int msize = 21; // most digits in a 64bit int (+sign +'\0')
+    char msg[msize];
+    if (read_socket(clsockfd, msg, msize) == 0) {
+        int dpid = atoi(msg);
+        prctl(PR_SET_PTRACER, dpid, 0, 0, 0);
+        // confirm change to DrKonqi
+        if (write_socket(clsockfd, msg, msize) == 0) {
+            fprintf(stderr, "KCrash: ptrace access transferred to %s\n", msg);
+        }
+    }
+    close(clsockfd);
+
+    return 1;
+}
+
+#endif
+
 #endif // Q_OS_UNIX


Reply via email to