ios: fix kill when running on device

Change-Id: I2bd9a461c055ef8aa5f5ed9facc879def0078f6f
Task-number: QTCREATORBUG-13259
Reviewed-by: Eike Ziller <eike.ziller@theqtcompany.com>
Reviewed-by: Christian Stenger <christian.stenger@theqtcompany.com>
Reviewed-by: Fawzi Mohamed <fawzi.mohamed@theqtcompany.com>
This commit is contained in:
Fawzi Mohamed
2014-12-01 15:26:13 +01:00
committed by Fawzi Mohamed
parent 6b894b50e6
commit a1076c209a
4 changed files with 85 additions and 23 deletions

View File

@@ -286,7 +286,8 @@ void IosToolHandlerPrivate::stop(int errorCode)
return; return;
} }
if (process.state() != QProcess::NotRunning) { if (process.state() != QProcess::NotRunning) {
process.terminate(); process.write("k\n\r");
process.closeWriteChannel();
killTimer.start(1500); killTimer.start(1500);
} }
} }

View File

@@ -311,8 +311,10 @@ public:
const QString &info); const QString &info);
void deviceWithId(QString deviceId, int timeout, DeviceAvailableCallback callback, void *userData); void deviceWithId(QString deviceId, int timeout, DeviceAvailableCallback callback, void *userData);
int processGdbServer(int fd); int processGdbServer(int fd);
void stopGdbServer(int fd, int phase);
private: private:
IosDeviceManager *q; IosDeviceManager *q;
QMutex m_sendMutex;
QHash<QString, AMDeviceRef> m_devices; QHash<QString, AMDeviceRef> m_devices;
QMultiHash<QString, PendingDeviceLookup *> m_pendingLookups; QMultiHash<QString, PendingDeviceLookup *> m_pendingLookups;
AMDeviceNotificationRef m_notification; AMDeviceNotificationRef m_notification;
@@ -631,7 +633,10 @@ enum GdbServerStatus {
int IosDeviceManagerPrivate::processGdbServer(int fd) int IosDeviceManagerPrivate::processGdbServer(int fd)
{ {
CommandSession session((QString())); CommandSession session((QString()));
session.sendGdbCommand(fd, "vCont;c"); // resume all threads {
QMutexLocker l(&m_sendMutex);
session.sendGdbCommand(fd, "vCont;c"); // resume all threads
}
GdbServerStatus state = NORMAL_PROCESS; GdbServerStatus state = NORMAL_PROCESS;
int maxRetry = 10; int maxRetry = 10;
int maxSignal = 5; int maxSignal = 5;
@@ -711,10 +716,17 @@ int IosDeviceManagerPrivate::processGdbServer(int fd)
addError(QLatin1String("hit maximum number of consecutive signals, stopping")); addError(QLatin1String("hit maximum number of consecutive signals, stopping"));
break; break;
} }
if (session.sendGdbCommand(fd, "vCont;c")) {
state = NORMAL_PROCESS; if (signal == 17) {
else state = NORMAL_PROCESS; // Ctrl-C to kill the process
break; } else {
QMutexLocker l(&m_sendMutex);
if (session.sendGdbCommand(fd, "vCont;c"))
state = NORMAL_PROCESS;
else
break;
}
}
} else { } else {
maxSignal = 5; maxSignal = 5;
} }
@@ -727,6 +739,16 @@ int IosDeviceManagerPrivate::processGdbServer(int fd)
return state != INFERIOR_EXITED; return state != INFERIOR_EXITED;
} }
void IosDeviceManagerPrivate::stopGdbServer(int fd, int phase)
{
CommandSession session((QString()));
QMutexLocker l(&m_sendMutex);
if (phase == 0)
session.writeAll(fd,"\x03",1);
else
session.sendGdbCommand(fd, "k", 1);
}
// ------- ConnectSession implementation -------- // ------- ConnectSession implementation --------
CommandSession::CommandSession(const QString &deviceId) : DeviceSession(deviceId), device(0), CommandSession::CommandSession(const QString &deviceId) : DeviceSession(deviceId), device(0),
@@ -1686,6 +1708,11 @@ int IosDeviceManager::processGdbServer(int fd)
return d->processGdbServer(fd); return d->processGdbServer(fd);
} }
void IosDeviceManager::stopGdbServer(int fd, int phase)
{
return d->stopGdbServer(fd, phase);
}
QStringList IosDeviceManager::errors() { QStringList IosDeviceManager::errors() {
return d->errors(); return d->errors();
} }

View File

@@ -75,6 +75,7 @@ public:
const QString &deviceId, int timeout = 1000); const QString &deviceId, int timeout = 1000);
void requestDeviceInfo(const QString &deviceId, int timeout = 1000); void requestDeviceInfo(const QString &deviceId, int timeout = 1000);
int processGdbServer(int fd); int processGdbServer(int fd);
void stopGdbServer(int fd, int phase);
QStringList errors(); QStringList errors();
signals: signals:
void deviceAdded(const QString &deviceId); void deviceAdded(const QString &deviceId);

View File

@@ -55,6 +55,7 @@
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#endif #endif
#include <thread>
// avoid utils dependency // avoid utils dependency
#define QTC_CHECK(cond) if (cond) {} else { qWarning() << "assert failed " << #cond << " " \ #define QTC_CHECK(cond) if (cond) {} else { qWarning() << "assert failed " << #cond << " " \
@@ -149,6 +150,7 @@ class GdbRunner: public QObject
Q_OBJECT Q_OBJECT
public: public:
GdbRunner(IosTool *iosTool, int gdbFd); GdbRunner(IosTool *iosTool, int gdbFd);
void stop(int phase);
public slots: public slots:
void run(); void run();
signals: signals:
@@ -174,7 +176,9 @@ public:
void writeMaybeBin(const QString &extraMsg, const char *msg, quintptr len); void writeMaybeBin(const QString &extraMsg, const char *msg, quintptr len);
public slots: public slots:
void errorMsg(const QString &msg); void errorMsg(const QString &msg);
void stopGdbRunner();
private slots: private slots:
void stopGdbRunner2();
void isTransferringApp(const QString &bundlePath, const QString &deviceId, int progress, void isTransferringApp(const QString &bundlePath, const QString &deviceId, int progress,
const QString &info); const QString &info);
void didTransferApp(const QString &bundlePath, const QString &deviceId, void didTransferApp(const QString &bundlePath, const QString &deviceId,
@@ -185,6 +189,8 @@ private slots:
void deviceInfo(const QString &deviceId, const Ios::IosDeviceManager::Dict &info); void deviceInfo(const QString &deviceId, const Ios::IosDeviceManager::Dict &info);
void appOutput(const QString &output); void appOutput(const QString &output);
private: private:
void readStdin();
QMutex m_xmlMutex; QMutex m_xmlMutex;
int maxProgress; int maxProgress;
int opLeft; int opLeft;
@@ -198,6 +204,7 @@ private:
QXmlStreamWriter out; QXmlStreamWriter out;
SingleRelayServer *gdbServer; SingleRelayServer *gdbServer;
GenericRelayServer *qmlServer; GenericRelayServer *qmlServer;
GdbRunner *gdbRunner;
friend class GdbRunner; friend class GdbRunner;
}; };
@@ -738,20 +745,17 @@ void IosTool::didStartApp(const QString &bundlePath, const QString &deviceId,
outFile.flush(); outFile.flush();
} }
if (!debug) { if (!debug) {
GdbRunner *gdbRunner = new GdbRunner(this, gdbFd); gdbRunner = new GdbRunner(this, gdbFd);
if (qmlServer) { // we should not stop the event handling of the main thread
// we should not stop the event handling of the main thread // all output moves to the new thread (other option would be to signal it back)
// all output moves to the new thread (other option would be to signal it back) QThread *gdbProcessThread = new QThread();
QThread *gdbProcessThread = new QThread(); gdbRunner->moveToThread(gdbProcessThread);
gdbRunner->moveToThread(gdbProcessThread); QObject::connect(gdbProcessThread, SIGNAL(started()), gdbRunner, SLOT(run()));
QObject::connect(gdbProcessThread, SIGNAL(started()), gdbRunner, SLOT(run())); QObject::connect(gdbRunner, SIGNAL(finished()), gdbProcessThread, SLOT(quit()));
QObject::connect(gdbRunner, SIGNAL(finished()), gdbProcessThread, SLOT(quit())); QObject::connect(gdbProcessThread, SIGNAL(finished()), gdbProcessThread, SLOT(deleteLater()));
QObject::connect(gdbProcessThread, SIGNAL(finished()), gdbProcessThread, SLOT(deleteLater())); gdbProcessThread->start();
gdbProcessThread->start();
} else { new std::thread([this]() -> void { readStdin();});
gdbRunner->setParent(this);
gdbRunner->run();
}
} }
} }
@@ -849,11 +853,36 @@ void IosTool::appOutput(const QString &output)
outFile.flush(); outFile.flush();
} }
void IosTool::readStdin()
{
int c = getchar();
if (c == 'k') {
QMetaObject::invokeMethod(this, "stopGdbRunner");
errorMsg(QLatin1String("iostool: Killing inferior.\n"));
} else if (c != EOF) {
errorMsg(QLatin1String("iostool: Unexpected character in stdin, stop listening.\n"));
}
}
void IosTool::errorMsg(const QString &msg) void IosTool::errorMsg(const QString &msg)
{ {
writeMsg(msg); writeMsg(msg);
} }
void IosTool::stopGdbRunner()
{
if (gdbRunner) {
gdbRunner->stop(0);
QTimer::singleShot(100, this, SLOT(stopGdbRunner2()));
}
}
void IosTool::stopGdbRunner2()
{
if (gdbRunner)
gdbRunner->stop(1);
}
void IosTool::stopRelayServers(int errorCode) void IosTool::stopRelayServers(int errorCode)
{ {
if (echoRelays) if (echoRelays)
@@ -886,9 +915,6 @@ int main(int argc, char *argv[])
exit(res); exit(res);
} }
#include "main.moc"
GdbRunner::GdbRunner(IosTool *iosTool, int gdbFd) : GdbRunner::GdbRunner(IosTool *iosTool, int gdbFd) :
QObject(0), m_iosTool(iosTool), m_gdbFd(gdbFd) QObject(0), m_iosTool(iosTool), m_gdbFd(gdbFd)
{ {
@@ -917,3 +943,10 @@ void GdbRunner::run()
m_iosTool->doExit(); m_iosTool->doExit();
emit finished(); emit finished();
} }
void GdbRunner::stop(int phase)
{
Ios::IosDeviceManager::instance()->stopGdbServer(m_gdbFd, phase);
}
#include "main.moc"