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 - lbeltrame@kde.org
+
+- 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
+
+- 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
#endif
#ifdef Q_OS_LINUX
+#include
#include
#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