Changeset View
Changeset View
Standalone View
Standalone View
src/drkonqibackends.cpp
Show All 17 Lines | |||||
18 | 18 | | |||
19 | #include <cstdlib> | 19 | #include <cstdlib> | ||
20 | #include <cerrno> | 20 | #include <cerrno> | ||
21 | #include <sys/types.h> | 21 | #include <sys/types.h> | ||
22 | #include <signal.h> | 22 | #include <signal.h> | ||
23 | 23 | | |||
24 | #include <QTimer> | 24 | #include <QTimer> | ||
25 | #include <QDir> | 25 | #include <QDir> | ||
26 | #include <QRegularExpression> | ||||
26 | 27 | | |||
27 | #include <KConfig> | 28 | #include <KConfig> | ||
28 | #include <KConfigGroup> | 29 | #include <KConfigGroup> | ||
29 | #include <KCrash> | 30 | #include <KCrash> | ||
30 | #include <QStandardPaths> | 31 | #include <QStandardPaths> | ||
31 | #include "drkonqi_debug.h" | 32 | #include "drkonqi_debug.h" | ||
32 | 33 | | |||
33 | #include "crashedapplication.h" | 34 | #include "crashedapplication.h" | ||
▲ Show 20 Lines • Show All 86 Lines • ▼ Show 20 Line(s) | 117 | { | |||
120 | a->m_version = DrKonqi::appVersion(); | 121 | a->m_version = DrKonqi::appVersion(); | ||
121 | a->m_reportAddress = BugReportAddress(DrKonqi::bugAddress()); | 122 | a->m_reportAddress = BugReportAddress(DrKonqi::bugAddress()); | ||
122 | a->m_pid = DrKonqi::pid(); | 123 | a->m_pid = DrKonqi::pid(); | ||
123 | a->m_signalNumber = DrKonqi::signal(); | 124 | a->m_signalNumber = DrKonqi::signal(); | ||
124 | a->m_restarted = DrKonqi::isRestarted(); | 125 | a->m_restarted = DrKonqi::isRestarted(); | ||
125 | a->m_thread = DrKonqi::thread(); | 126 | a->m_thread = DrKonqi::thread(); | ||
126 | 127 | | |||
127 | //try to determine the executable that crashed | 128 | //try to determine the executable that crashed | ||
128 | if ( QFileInfo(QStringLiteral("/proc/%1/exe").arg(a->m_pid)).exists() ) { | 129 | const QString procPath(QStringLiteral("/proc/%1").arg(a->m_pid)); | ||
130 | const QString exeProcPath(procPath + QStringLiteral("/exe")); | ||||
131 | if (QFileInfo(exeProcPath).exists()) { | ||||
129 | //on linux, the fastest and most reliable way is to get the path from /proc | 132 | //on linux, the fastest and most reliable way is to get the path from /proc | ||
130 | qCDebug(DRKONQI_LOG) << "Using /proc to determine executable path"; | 133 | qCDebug(DRKONQI_LOG) << "Using /proc to determine executable path"; | ||
131 | a->m_executable.setFile(QFile::symLinkTarget(QStringLiteral("/proc/%1/exe").arg(a->m_pid))); | 134 | const QString exePath = QFile::symLinkTarget(exeProcPath); | ||
132 | 135 | | |||
136 | a->m_executable.setFile(exePath); | ||||
133 | if (DrKonqi::isKdeinit() || | 137 | if (DrKonqi::isKdeinit() || | ||
134 | a->m_executable.fileName().startsWith(QLatin1String("python")) ) { | 138 | a->m_executable.fileName().startsWith(QLatin1String("python")) ) { | ||
135 | | ||||
136 | a->m_fakeBaseName = DrKonqi::appName(); | 139 | a->m_fakeBaseName = DrKonqi::appName(); | ||
137 | } | 140 | } | ||
141 | | ||||
142 | QDir mapFilesDir(procPath + QStringLiteral("/map_files")); | ||||
143 | mapFilesDir.setFilter(mapFilesDir.filter() | QDir::System); // proc is system! | ||||
144 | | ||||
145 | // "/bin/foo (deleted)" is how the kernel tells us that a file has been deleted since | ||||
146 | // it was mmap'd. | ||||
147 | QRegularExpression expression(QStringLiteral("(?<path>.+) \\(deleted\\)$")); | ||||
148 | // For the map_files we filter only .so files to ensure that | ||||
149 | // we don't trip over cache files or the like, as a result we | ||||
150 | // manually need to check if the main exe was deleted and add | ||||
151 | // it. | ||||
152 | // NB: includes .so* and .py* since we also implicitly support snakes to | ||||
153 | // a degree | ||||
154 | QRegularExpression soExpression(QStringLiteral("(?<path>.+\\.(so|py)([^/]*)) \\(deleted\\)$")); | ||||
155 | | ||||
156 | bool hasDeletedFiles = false; | ||||
157 | | ||||
158 | const auto exeMatch = expression.match(exePath); | ||||
159 | if (exeMatch.isValid() && exeMatch.hasMatch()) { | ||||
160 | hasDeletedFiles = true; | ||||
161 | } | ||||
162 | | ||||
163 | const auto list = mapFilesDir.entryInfoList(); | ||||
164 | for (auto it = list.constBegin(); !hasDeletedFiles && it != list.constEnd(); ++it) { | ||||
165 | const auto match = soExpression.match(it->symLinkTarget()); | ||||
166 | if (!match.isValid() || !match.hasMatch()) { | ||||
167 | continue; | ||||
168 | } | ||||
169 | hasDeletedFiles = true; | ||||
170 | } | ||||
171 | | ||||
172 | a->m_hasDeletedFiles = hasDeletedFiles; | ||||
apol: Maybe we don't need to store all of them? I only see it used as "isEmpty()". | |||||
I suppose, my plan was actually to list the changed files but I've seen abandoned that idea because it's largely useless information. I'll change it to a bool. sitter: I suppose, my plan was actually to list the changed files but I've seen abandoned that idea… | |||||
sitter: *since abandoned | |||||
173 | | ||||
174 | qCDebug(DRKONQI_LOG) << "exe" << exePath << "has deleted files:" << hasDeletedFiles; | ||||
138 | } else { | 175 | } else { | ||
139 | if ( DrKonqi::isKdeinit() ) { | 176 | if ( DrKonqi::isKdeinit() ) { | ||
140 | a->m_executable = QFileInfo(QStandardPaths::findExecutable(QStringLiteral("kdeinit5"))); | 177 | a->m_executable = QFileInfo(QStandardPaths::findExecutable(QStringLiteral("kdeinit5"))); | ||
141 | a->m_fakeBaseName = DrKonqi::appName(); | 178 | a->m_fakeBaseName = DrKonqi::appName(); | ||
142 | } else { | 179 | } else { | ||
143 | QFileInfo execPath(DrKonqi::appName()); | 180 | QFileInfo execPath(DrKonqi::appName()); | ||
144 | if ( execPath.isAbsolute() ) { | 181 | if ( execPath.isAbsolute() ) { | ||
145 | a->m_executable = execPath; | 182 | a->m_executable = execPath; | ||
▲ Show 20 Lines • Show All 96 Lines • Show Last 20 Lines |
Maybe we don't need to store all of them? I only see it used as "isEmpty()".