diff options
author | Vikas Pachdha <[email protected]> | 2016-12-19 18:41:00 +0100 |
---|---|---|
committer | Vikas Pachdha <[email protected]> | 2016-12-20 16:09:14 +0000 |
commit | ccc5359c420dd8388cb5a55aa0948b9297027b08 (patch) | |
tree | 95e2f23703155312abfa1a554a89c3794b1edc5a /src/plugins/ios/iostoolhandler.cpp | |
parent | 8751d46f971837fc2c1505d38ed7d050e16a7a69 (diff) |
iOS: Remove the step to spawn the app before launch on iOS
This causes timing issues on certain devices resulting in
app startup failure
Task-number: QTCREATORBUG-17336
Change-Id: I190b5415bdef1fc80a415b0cb872b95b883db5d8
Reviewed-by: Eike Ziller <[email protected]>
Diffstat (limited to 'src/plugins/ios/iostoolhandler.cpp')
-rw-r--r-- | src/plugins/ios/iostoolhandler.cpp | 135 |
1 files changed, 35 insertions, 100 deletions
diff --git a/src/plugins/ios/iostoolhandler.cpp b/src/plugins/ios/iostoolhandler.cpp index 3af160caddc..b12df9be16c 100644 --- a/src/plugins/ios/iostoolhandler.cpp +++ b/src/plugins/ios/iostoolhandler.cpp @@ -34,6 +34,7 @@ #include <utils/qtcassert.h> #include <utils/fileutils.h> #include "utils/runextensions.h" +#include "utils/synchronousprocess.h" #include <QCoreApplication> #include <QFileInfo> @@ -141,7 +142,6 @@ public: bool isRunning(); void start(const QString &exe, const QStringList &args); virtual void stop(int errorCode) = 0; - virtual void debuggerStateChanged(Debugger::DebuggerState state) { Q_UNUSED(state); } // signals void isTransferringApp(const QString &bundlePath, const QString &deviceId, int progress, @@ -230,20 +230,10 @@ private: * YES | * | | * v | - * +---------+-------------------------+ | - * | SimulatorControl::spawnAppProcess | <------------------+ - * +-----------------------------------+ - * | - * v - * +--------+-----------+ +-----------------------------+ - * | Debug Run ? +---YES------> + Wait for debugger to attach | - * +---------+----------+ +-----------+-----------------+ - * NO | - * | | - * v | - * +-----------------------------+ | - * | SimulatorControl::launchApp | <-------------------+ - * +-----------------------------+ + * +---------+------------------------------+ | + * | SimulatorControl::launchAppOnSimulator | <-------------+ + * +----------------------------------------+ + * ***************************************************************************/ class IosSimulatorToolHandlerPrivate : public IosToolHandlerPrivate { @@ -260,15 +250,11 @@ public: const QString &deviceIdentifier, int timeout = 1000) override; void requestDeviceInfo(const QString &deviceId, int timeout = 1000) override; void stop(int errorCode) override; - void debuggerStateChanged(Debugger::DebuggerState state) override; private: void installAppOnSimulator(); - void spawnAppOnSimulator(const QStringList &extraArgs); - void launchAppOnSimulator(); - + void launchAppOnSimulator(const QStringList &extraArgs); bool isResponseValid(const SimulatorControl::ResponseData &responseData); - void onResponseAppSpawn(const SimulatorControl::ResponseData &response); void simAppProcessError(QProcess::ProcessError error); void simAppProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); @@ -277,7 +263,6 @@ private: private: qint64 appPId = -1; - bool appLaunched = false; SimulatorControl *simCtl; QList<QFuture<void>> futureList; }; @@ -802,7 +787,7 @@ void IosSimulatorToolHandlerPrivate::requestRunApp(const QString &appBundlePath, if (isResponseValid(response)) return; if (response.success) { - spawnAppOnSimulator(extraArgs); + launchAppOnSimulator(extraArgs); } else { errorMsg(IosToolHandler::tr("Application launch on Simulator failed. Simulator not running.") .arg(bundlePath)); @@ -811,7 +796,7 @@ void IosSimulatorToolHandlerPrivate::requestRunApp(const QString &appBundlePath, }; if (SimulatorControl::isSimulatorRunning(deviceId)) - spawnAppOnSimulator(extraArgs); + launchAppOnSimulator(extraArgs); else futureList << Utils::onResultReady(simCtl->startSimulator(deviceId), onSimulatorStart); } @@ -824,14 +809,7 @@ void IosSimulatorToolHandlerPrivate::requestDeviceInfo(const QString &deviceId, void IosSimulatorToolHandlerPrivate::stop(int errorCode) { - - if (process) { - QTC_ASSERT(process.unique(), process->kill(); qCDebug(toolHandlerLog)<<"App process is not unique."); - process.reset(); - appPId = -1; - appLaunched = false; - } - + appPId = -1; foreach (auto f, futureList) { if (!f.isFinished()) f.cancel(); @@ -841,14 +819,6 @@ void IosSimulatorToolHandlerPrivate::stop(int errorCode) q->finished(q); } -void IosSimulatorToolHandlerPrivate::debuggerStateChanged(Debugger::DebuggerState state) -{ - if (!appLaunched && state == Debugger::DebuggerState::InferiorRunOk) { - // Debugger attached. Launch it on the simulator. - launchAppOnSimulator(); - } -} - void IosSimulatorToolHandlerPrivate::installAppOnSimulator() { auto onResponseAppInstall = [this](const SimulatorControl::ResponseData &response) { @@ -871,23 +841,32 @@ void IosSimulatorToolHandlerPrivate::installAppOnSimulator() onResponseAppInstall); } -void IosSimulatorToolHandlerPrivate::spawnAppOnSimulator(const QStringList &extraArgs) +void IosSimulatorToolHandlerPrivate::launchAppOnSimulator(const QStringList &extraArgs) { - Utils::FileName appBundle = Utils::FileName::fromString(bundlePath); - bool debugRun = runKind == IosToolHandler::DebugRun; - futureList << Utils::onResultReady(simCtl->spawnAppProcess(deviceId, appBundle, debugRun, extraArgs), - std::bind(&IosSimulatorToolHandlerPrivate::onResponseAppSpawn, this, _1)); -} + auto monitorPid = [this](QFutureInterface<int> &fi, qint64 pid) { + int exitCode = 0; + const QStringList args({QStringLiteral("-0"), QString::number(pid)}); + Utils::SynchronousProcess pKill; + while (!fi.isCanceled() && exitCode == 0) { + // Poll every 1 sec to check whether the app is running. + QThread::msleep(1000); + Utils::SynchronousProcessResponse resp = pKill.runBlocking(QStringLiteral("kill"), args); + exitCode = resp.exitCode; + } + // Future is cancelled if the app is stopped from the qt creator. + if (!fi.isCanceled()) + stop(0); + }; -void IosSimulatorToolHandlerPrivate::launchAppOnSimulator() -{ - auto onResponseAppLaunch = [this](const SimulatorControl::ResponseData &response) { + auto onResponseAppLaunch = [this, monitorPid](const SimulatorControl::ResponseData &response) { if (!isResponseValid(response)) return; - - if (response.pID != -1) { - appLaunched = true; + if (response.success) { + appPId = response.pID; + gotInferiorPid(bundlePath, deviceId, appPId); didStartApp(bundlePath, deviceId, Ios::IosToolHandler::Success); + // Start monitoring app's life signs. + futureList << Utils::runAsync(monitorPid, appPId); } else { errorMsg(IosToolHandler::tr("Application launch on Simulator failed. %1") .arg(QString::fromLocal8Bit(response.commandOutput))); @@ -896,16 +875,11 @@ void IosSimulatorToolHandlerPrivate::launchAppOnSimulator() q->finished(q); } }; - - if (appPId != -1) { - Utils::FileName appBundle = Utils::FileName::fromString(bundlePath); - futureList << Utils::onResultReady(simCtl->launchApp(deviceId, - SimulatorControl::bundleIdentifier(appBundle), appPId), - onResponseAppLaunch); - } else { - errorMsg(IosToolHandler::tr("Spawning the Application process on Simulator failed. Spawning timed out.")); - didStartApp(bundlePath, deviceId, Ios::IosToolHandler::Failure); - } + Utils::FileName appBundle = Utils::FileName::fromString(bundlePath); + futureList << Utils::onResultReady(simCtl->launchApp(deviceId, + SimulatorControl::bundleIdentifier(appBundle), + runKind == IosToolHandler::DebugRun, + extraArgs), onResponseAppLaunch); } bool IosSimulatorToolHandlerPrivate::isResponseValid(const SimulatorControl::ResponseData &responseData) @@ -921,40 +895,6 @@ bool IosSimulatorToolHandlerPrivate::isResponseValid(const SimulatorControl::Res return true; } -void IosSimulatorToolHandlerPrivate::onResponseAppSpawn(const SimulatorControl::ResponseData &response) -{ - if (!isResponseValid(response)) - return; - - if (response.processInstance) { - QTC_ASSERT(!process || !isRunning(), - qCDebug(toolHandlerLog) << "Spwaning app while an app instance exits."); - process = response.processInstance; - QObject::connect(process.get(), &QProcess::readyReadStandardOutput, - std::bind(&IosSimulatorToolHandlerPrivate::simAppProcessHasData, this)); - QObject::connect(process.get(), &QProcess::readyReadStandardError, - std::bind(&IosSimulatorToolHandlerPrivate::simAppProcessHasErrorOutput, this)); - QObject::connect(process.get(), static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), - std::bind(&IosSimulatorToolHandlerPrivate::simAppProcessFinished, this, _1, _2)); - QObject::connect(process.get(), &QProcess::errorOccurred, - std::bind(&IosSimulatorToolHandlerPrivate::simAppProcessError, this, _1)); - - appPId = response.pID; - gotInferiorPid(bundlePath, deviceId, appPId); - - // For normal run. Launch app on Simulator. - // For debug run, wait for the debugger to attach and then launch the app. - if (runKind == IosToolHandler::NormalRun) - launchAppOnSimulator(); - } else { - errorMsg(IosToolHandler::tr("Spawning the Application process on Simulator failed. %1") - .arg(QString::fromLocal8Bit(response.commandOutput))); - didStartApp(bundlePath, deviceId, Ios::IosToolHandler::Failure); - stop(-1); - q->finished(q); - } -} - void IosSimulatorToolHandlerPrivate::simAppProcessError(QProcess::ProcessError error) { errorMsg(IosToolHandler::tr("Simulator application process error %1").arg(error)); @@ -1010,11 +950,6 @@ void IosToolHandler::stop() d->stop(-1); } -void IosToolHandler::debuggerStateChanged(int state) -{ - d->debuggerStateChanged((Debugger::DebuggerState)state); -} - void IosToolHandler::requestTransferApp(const QString &bundlePath, const QString &deviceId, int timeout) { |