aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcus Tillmanns <marcus.tillmanns@qt.io>2023-08-29 09:24:35 +0200
committerMarcus Tillmanns <marcus.tillmanns@qt.io>2023-08-29 13:25:08 +0000
commit373886bc21926e77803110765d90a339b57d3af2 (patch)
tree18f64d8139afa142abeb5f7815ca76a3cdba7cd5
parentda7c25e8da3a41e076506eda2f050af452bf36c5 (diff)
ProcessStub: Fix start sequencing
An application that is using ptrace will send SIGTRAP as soon as it reaches its execve call. The process stub previously expected the only signal sent from the inferior to be SIGSTOP due to the PTRACE_DETACH call with the SIGSTOP argument. This meant that a race could occur where the SIGTRAP was received instead of the SIGSTOP and so the PTRACE_DETACH did not actually detach correctly. This patch fixes it so that it first waits for the SIGTRAP and then calls detach and waits for the expected SIGSTOP. Should this fail, more debug output is added to ease debugging failures. Fixes: QTCREATORBUG-29463 Change-Id: Ibac8b75de0c5604aeb20faba8aff58633329341e Reviewed-by: Artem Sokolovskii <artem.sokolovskii@qt.io> Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Christian Stenger <christian.stenger@qt.io>
-rw-r--r--src/plugins/debugger/gdb/gdbengine.cpp8
-rw-r--r--src/tools/process_stub/main.cpp52
2 files changed, 45 insertions, 15 deletions
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index d52e2bc710..49d28c46fd 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -1450,9 +1450,11 @@ void GdbEngine::handleStop2(const GdbMi &data)
void GdbEngine::handleStop3()
{
- DebuggerCommand cmd("-thread-info", Discardable);
- cmd.callback = CB(handleThreadInfo);
- runCommand(cmd);
+ if (terminal() && state() != InferiorRunOk) {
+ DebuggerCommand cmd("-thread-info", Discardable);
+ cmd.callback = CB(handleThreadInfo);
+ runCommand(cmd);
+ }
}
void GdbEngine::handleShowVersion(const DebuggerResponse &response)
diff --git a/src/tools/process_stub/main.cpp b/src/tools/process_stub/main.cpp
index c54480af4c..3749333e46 100644
--- a/src/tools/process_stub/main.cpp
+++ b/src/tools/process_stub/main.cpp
@@ -211,6 +211,38 @@ void onInferiorErrorOccurered(QProcess::ProcessError error)
qCWarning(log) << "Inferior error: " << error << inferiorProcess.errorString();
}
+#ifdef Q_OS_LINUX
+QString statusToString(int status)
+{
+ if (WIFEXITED(status))
+ return QString("exit, status=%1").arg(WEXITSTATUS(status));
+ else if (WIFSIGNALED(status))
+ return QString("Killed by: %1").arg(WTERMSIG(status));
+ else if (WIFSTOPPED(status)) {
+ return QString("Stopped by: %1").arg(WSTOPSIG(status));
+ } else if (WIFCONTINUED(status))
+ return QString("Continued");
+
+ return QString("Unknown status");
+}
+
+bool waitFor(int signalToWaitFor)
+{
+ int status = 0;
+
+ waitpid(inferiorId, &status, WUNTRACED);
+
+ if (!WIFSTOPPED(status) || WSTOPSIG(status) != signalToWaitFor) {
+ qCCritical(log) << "Unexpected status during startup:" << statusToString(status)
+ << ", aborting";
+ sendCrash(0xFF);
+ return false;
+ }
+
+ return true;
+}
+#endif
+
void onInferiorStarted()
{
inferiorId = inferiorProcess.processId();
@@ -223,25 +255,21 @@ void onInferiorStarted()
if (!debugMode)
sendPid(inferiorId);
#else
+
if (debugMode) {
+ qCInfo(log) << "Waiting for SIGTRAP from inferiors execve ...";
+ if (!waitFor(SIGTRAP))
+ return;
+
qCInfo(log) << "Detaching ...";
ptrace(PTRACE_DETACH, inferiorId, 0, SIGSTOP);
// Wait until the process actually finished detaching
- int status = 0;
- waitpid(inferiorId, &status, WUNTRACED);
- if (log().isInfoEnabled()) {
- if (WIFEXITED(status))
- qCInfo(log) << "inferior exited, status=" << WEXITSTATUS(status);
- else if (WIFSIGNALED(status))
- qCInfo(log) << "inferior killed by signal" << WTERMSIG(status);
- else if (WIFSTOPPED(status))
- qCInfo(log) << "inferior stopped by signal" << WSTOPSIG(status);
- else if (WIFCONTINUED(status))
- qCInfo(log) << "inferior continued";
- }
+ if (!waitFor(SIGSTOP))
+ return;
}
+ qCInfo(log) << "Sending pid:" << inferiorId;
sendPid(inferiorId);
#endif
}