summaryrefslogtreecommitdiff
path: root/src/plugins/debugger/gdb/remotegdbprocess.cpp
diff options
context:
space:
mode:
authorck <qt-info@nokia.com>2010-07-12 09:33:22 +0200
committerck <qt-info@nokia.com>2010-07-12 09:33:22 +0200
commit65eb1d551592421f5e0e961c8c1dd2d056023697 (patch)
treee4698e3ee36443d67911ff0de3b9637aa0917484 /src/plugins/debugger/gdb/remotegdbprocess.cpp
parente43287fb3a4e2b69ada07455760aa30afb7eb10c (diff)
downloadqt-creator-65eb1d551592421f5e0e961c8c1dd2d056023697.tar.gz
Replace SSH library.
Diffstat (limited to 'src/plugins/debugger/gdb/remotegdbprocess.cpp')
-rw-r--r--src/plugins/debugger/gdb/remotegdbprocess.cpp250
1 files changed, 118 insertions, 132 deletions
diff --git a/src/plugins/debugger/gdb/remotegdbprocess.cpp b/src/plugins/debugger/gdb/remotegdbprocess.cpp
index fb7e2d0281..7288f44c7b 100644
--- a/src/plugins/debugger/gdb/remotegdbprocess.cpp
+++ b/src/plugins/debugger/gdb/remotegdbprocess.cpp
@@ -33,14 +33,15 @@
#include <ctype.h>
+using namespace Core;
+
namespace Debugger {
namespace Internal {
-RemoteGdbProcess::RemoteGdbProcess(const Core::SshServerInfo &server,
+RemoteGdbProcess::RemoteGdbProcess(const Core::SshConnectionParameters &connParams,
RemotePlainGdbAdapter *adapter, QObject *parent)
- : AbstractGdbProcess(parent), m_serverInfo(server), m_adapter(adapter)
+ : AbstractGdbProcess(parent), m_connParams(connParams), m_adapter(adapter)
{
-
}
QByteArray RemoteGdbProcess::readAllStandardOutput()
@@ -59,68 +60,122 @@ QByteArray RemoteGdbProcess::readAllStandardError()
void RemoteGdbProcess::start(const QString &cmd, const QStringList &args)
{
- m_gdbConn = Core::InteractiveSshConnection::create(m_serverInfo);
- m_appOutputConn = Core::InteractiveSshConnection::create(m_serverInfo);
- m_errOutputConn = Core::InteractiveSshConnection::create(m_serverInfo);
m_command = cmd;
m_cmdArgs = args;
- m_errOutputConn->start();
- m_appOutputConn->start();
- m_gdbConn->start();
- }
+ m_gdbStarted = false;
+ m_error.clear();
+ m_conn = SshConnection::create();
+ connect(m_conn.data(), SIGNAL(connected()), this, SLOT(handleConnected()));
+ connect(m_conn.data(), SIGNAL(error(SshError)), this,
+ SLOT(handleConnectionError()));
+ m_conn->connectToHost(m_connParams);
+}
-bool RemoteGdbProcess::waitForStarted()
+void RemoteGdbProcess::handleConnected()
{
- if (!waitForInputReady(m_appOutputConn))
- return false;
- if (!sendAndWaitForEcho(m_appOutputConn, readerCmdLine(AppOutputFile)))
- return false;
- if (!waitForInputReady(m_errOutputConn))
- return false;
- if (!sendAndWaitForEcho(m_errOutputConn, readerCmdLine(ErrOutputFile)))
- return false;
- if (!waitForInputReady(m_gdbConn))
- return false;
- connect(m_appOutputConn.data(), SIGNAL(remoteOutputAvailable()),
- this, SLOT(handleAppOutput()));
- connect(m_errOutputConn.data(), SIGNAL(remoteOutputAvailable()),
- this, SLOT(handleErrOutput()));
- connect(m_gdbConn.data(), SIGNAL(remoteOutputAvailable()),
- this, SLOT(handleGdbOutput()));
- m_gdbStarted = false;
- m_gdbCmdLine = "stty -echo && DISPLAY=:0.0 " + m_command.toUtf8() + ' '
+ m_fifoCreator = m_conn->createRemoteProcess( "rm -f "
+ + AppOutputFile + " && mkfifo " + AppOutputFile);
+ connect(m_fifoCreator.data(), SIGNAL(closed(int)), this,
+ SLOT(handleFifoCreationFinished(int)));
+ m_fifoCreator->start();
+}
+
+void RemoteGdbProcess::handleConnectionError()
+{
+ emitErrorExit(tr("Connection could not be established."));
+}
+
+void RemoteGdbProcess::handleFifoCreationFinished(int exitStatus)
+{
+ if (exitStatus != SshRemoteProcess::ExitedNormally) {
+ emitErrorExit(tr("Could not create FIFO."));
+ } else {
+ m_appOutputReader = m_conn->createRemoteProcess("cat " + AppOutputFile);
+ connect(m_appOutputReader.data(), SIGNAL(started()), this,
+ SLOT(handleAppOutputReaderStarted()));
+ connect(m_appOutputReader.data(), SIGNAL(closed(int)), this,
+ SLOT(handleAppOutputReaderFinished(int)));
+ m_appOutputReader->start();
+ }
+}
+
+void RemoteGdbProcess::handleAppOutputReaderStarted()
+{
+ connect(m_appOutputReader.data(), SIGNAL(outputAvailable(QByteArray)),
+ this, SLOT(handleAppOutput(QByteArray)));
+ QByteArray cmdLine = "DISPLAY=:0.0 " + m_command.toUtf8() + ' '
+ m_cmdArgs.join(QLatin1String(" ")).toUtf8()
- + " -tty=" + AppOutputFile + " 2>" + ErrOutputFile + '\n';
+ + " -tty=" + AppOutputFile;
if (!m_wd.isEmpty())
- m_gdbCmdLine.prepend("cd " + m_wd.toUtf8() + " && ");
- if (sendInput(m_gdbCmdLine) != m_gdbCmdLine.count())
- return false;
+ cmdLine.prepend("cd " + m_wd.toUtf8() + " && ");
+ m_gdbProc = m_conn->createRemoteProcess(cmdLine);
+ connect(m_gdbProc.data(), SIGNAL(started()), this,
+ SLOT(handleGdbStarted()));
+ connect(m_gdbProc.data(), SIGNAL(closed(int)), this,
+ SLOT(handleGdbFinished(int)));
+ connect(m_gdbProc.data(), SIGNAL(outputAvailable(QByteArray)), this,
+ SLOT(handleGdbOutput(QByteArray)));
+ connect(m_gdbProc.data(), SIGNAL(errorOutputAvailable(QByteArray)), this,
+ SLOT(handleErrOutput(QByteArray)));
+ m_gdbProc->start();
+}
+
+void RemoteGdbProcess::handleAppOutputReaderFinished(int exitStatus)
+{
+ if (exitStatus != SshRemoteProcess::ExitedNormally)
+ emitErrorExit(tr("Application output reader unexpectedly finished."));
+}
- return true;
+void RemoteGdbProcess::handleGdbStarted()
+{
+ m_gdbStarted = true;
+}
+
+void RemoteGdbProcess::handleGdbFinished(int exitStatus)
+{
+ switch (exitStatus) {
+ case SshRemoteProcess::FailedToStart:
+ emitErrorExit(tr("Remote gdb failed to start."));
+ break;
+ case SshRemoteProcess::KilledBySignal:
+ emitErrorExit(tr("Remote gdb crashed."));
+ break;
+ case SshRemoteProcess::ExitedNormally:
+ emit finished(m_gdbProc->exitCode(), QProcess::NormalExit);
+ break;
+ }
+ disconnect(m_conn.data(), 0, this, 0);
+ m_gdbProc = SshRemoteProcess::Ptr();
+ m_appOutputReader = SshRemoteProcess::Ptr();
+ m_conn->disconnectFromHost();
+}
+
+bool RemoteGdbProcess::waitForStarted()
+{
+ return m_error.isEmpty();
}
qint64 RemoteGdbProcess::write(const QByteArray &data)
{
- if (!m_gdbStarted || !m_inputToSend.isEmpty() || !m_lastSeqNr.isEmpty()) {
+ if (!m_gdbStarted || !m_inputToSend.isEmpty() || !m_lastSeqNr.isEmpty())
m_inputToSend.enqueue(data);
- return data.size();
- } else {
- return sendInput(data);
- }
+ else
+ sendInput(data);
+ return data.size();
}
void RemoteGdbProcess::kill()
{
- stopReaders();
- Core::InteractiveSshConnection::Ptr controlConn
- = Core::InteractiveSshConnection::create(m_serverInfo);
- if (!controlConn->hasError()) {
- if (controlConn->start())
- controlConn->sendInput("pkill -x gdb\r\n");
- }
+ SshRemoteProcess::Ptr killProc
+ = m_conn->createRemoteProcess("pkill -SIGKILL -x gdb");
+ killProc->start();
+}
- m_gdbConn->quit();
- emit finished(0, QProcess::CrashExit);
+void RemoteGdbProcess::interruptInferior()
+{
+ SshRemoteProcess::Ptr intProc
+ = m_conn->createRemoteProcess("pkill -x -SIGINT gdb");
+ intProc->start();
}
QProcess::ProcessState RemoteGdbProcess::state() const
@@ -130,35 +185,19 @@ QProcess::ProcessState RemoteGdbProcess::state() const
QString RemoteGdbProcess::errorString() const
{
- return m_gdbConn ? m_gdbConn->error() : QString();
+ return m_error;
}
-void RemoteGdbProcess::handleGdbOutput()
+void RemoteGdbProcess::handleGdbOutput(const QByteArray &output)
{
- m_currentGdbOutput
- += removeCarriageReturn(m_gdbConn->waitForRemoteOutput(0));
+ // TODO: Carriage return removal still necessary?
+ m_currentGdbOutput += removeCarriageReturn(output);
#if 0
qDebug("%s: complete unread output is '%s'", Q_FUNC_INFO, m_currentGdbOutput.data());
#endif
- if (checkForGdbExit(m_currentGdbOutput)) {
- m_currentGdbOutput.clear();
- return;
- }
-
if (!m_currentGdbOutput.endsWith('\n'))
return;
- if (!m_gdbStarted) {
- const int index = m_currentGdbOutput.indexOf(m_gdbCmdLine);
- if (index != -1)
- m_currentGdbOutput.remove(index, m_gdbCmdLine.size());
- // Note: We can't guarantee that we will match the command line,
- // because the remote terminal sometimes inserts control characters.
- // Otherwise we could set m_gdbStarted here.
- }
-
- m_gdbStarted = true;
-
if (m_currentGdbOutput.contains(m_lastSeqNr + '^'))
m_lastSeqNr.clear();
@@ -187,7 +226,7 @@ QProcessEnvironment RemoteGdbProcess::processEnvironment() const
void RemoteGdbProcess::setProcessEnvironment(const QProcessEnvironment & /* env */)
{
- // TODO: Do something.
+ // TODO: Do something. (if remote process exists: set, otherwise queue)
}
void RemoteGdbProcess::setEnvironment(const QStringList & /* env */)
@@ -211,48 +250,27 @@ int RemoteGdbProcess::findAnchor(const QByteArray &data) const
return -1;
}
-qint64 RemoteGdbProcess::sendInput(const QByteArray &data)
+void RemoteGdbProcess::sendInput(const QByteArray &data)
{
int pos;
for (pos = 0; pos < data.size(); ++pos)
if (!isdigit(data.at(pos)))
break;
m_lastSeqNr = data.left(pos);
- return m_gdbConn->sendInput(data) ? data.size() : 0;
+ m_gdbProc->sendInput(data);
}
-void RemoteGdbProcess::handleAppOutput()
+void RemoteGdbProcess::handleAppOutput(const QByteArray &output)
{
- m_adapter->handleApplicationOutput(m_appOutputConn->waitForRemoteOutput(0));
+ m_adapter->handleApplicationOutput(output);
}
-void RemoteGdbProcess::handleErrOutput()
+void RemoteGdbProcess::handleErrOutput(const QByteArray &output)
{
- m_errorOutput += m_errOutputConn->waitForRemoteOutput(0);
+ m_errorOutput += output;
emit readyReadStandardError();
}
-void RemoteGdbProcess::stopReaders()
-{
- if (m_appOutputConn) {
- disconnect(m_appOutputConn.data(), SIGNAL(remoteOutputAvailable()),
- this, SLOT(handleAppOutput()));
- m_appOutputConn->sendInput(CtrlC);
- m_appOutputConn->quit();
- }
- if (m_errOutputConn) {
- disconnect(m_errOutputConn.data(), SIGNAL(remoteOutputAvailable()),
- this, SLOT(handleErrOutput()));
- m_errOutputConn->sendInput(CtrlC);
- m_errOutputConn->quit();
- }
-}
-
-QByteArray RemoteGdbProcess::readerCmdLine(const QByteArray &file)
-{
- return "rm -f " + file + " && mkfifo " + file + " && cat " + file + "\r\n";
-}
-
QByteArray RemoteGdbProcess::removeCarriageReturn(const QByteArray &data)
{
QByteArray output;
@@ -264,48 +282,16 @@ QByteArray RemoteGdbProcess::removeCarriageReturn(const QByteArray &data)
return output;
}
-bool RemoteGdbProcess::checkForGdbExit(QByteArray &output)
+void RemoteGdbProcess::emitErrorExit(const QString &error)
{
- const QByteArray exitString("^exit");
- const int exitPos = output.indexOf(exitString);
- if (exitPos == -1)
- return false;
-
- emit finished(0, QProcess::NormalExit);
- disconnect(m_gdbConn.data(), SIGNAL(remoteOutputAvailable()),
- this, SLOT(handleGdbOutput()));
- output.remove(exitPos + exitString.size(), output.size());
- stopReaders();
- return true;
-}
-
-bool RemoteGdbProcess::waitForInputReady(Core::InteractiveSshConnection::Ptr &conn)
-{
- if (conn->waitForRemoteOutput(m_serverInfo.timeout).isEmpty())
- return false;
- while (!conn->waitForRemoteOutput(100).isEmpty())
- ;
- return true;
-}
-
-bool RemoteGdbProcess::sendAndWaitForEcho(Core::InteractiveSshConnection::Ptr &conn,
- const QByteArray &cmdLine)
-{
- conn->sendInput(cmdLine);
- QByteArray allOutput;
- while (!allOutput.endsWith(cmdLine)) {
- const QByteArray curOutput = conn->waitForRemoteOutput(100);
- if (curOutput.isEmpty())
- return false;
- allOutput += curOutput;
+ if (m_error.isEmpty()) {
+ m_error = error;
+ emit finished(-1, QProcess::CrashExit);
}
- return true;
}
-
const QByteArray RemoteGdbProcess::CtrlC = QByteArray(1, 0x3);
const QByteArray RemoteGdbProcess::AppOutputFile("app_output");
-const QByteArray RemoteGdbProcess::ErrOutputFile("err_output");
} // namespace Internal
} // namespace Debugger