diff options
author | Marcus Tillmanns <marcus.tillmanns@qt.io> | 2023-08-29 09:24:35 +0200 |
---|---|---|
committer | Marcus Tillmanns <marcus.tillmanns@qt.io> | 2023-08-29 13:25:08 +0000 |
commit | 373886bc21926e77803110765d90a339b57d3af2 (patch) | |
tree | 18f64d8139afa142abeb5f7815ca76a3cdba7cd5 | |
parent | da7c25e8da3a41e076506eda2f050af452bf36c5 (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.cpp | 8 | ||||
-rw-r--r-- | src/tools/process_stub/main.cpp | 52 |
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 } |