From c97a54cebf3adec2cfa89bfa31ac02f0741e063c Mon Sep 17 00:00:00 2001
From: Vikas Pachdha <vikas.pachdha@qt.io>
Date: Wed, 8 Feb 2017 11:41:42 +0100
Subject: [PATCH] Android: Fix crash on using Re-run app

Collaterally busybox detection(dead code) is removed

Task-number: QTCREATORBUG-17691
Change-Id: I50de3e4ad299c741c9b1afaddb22209b409acccf
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
---
 src/plugins/android/androidrunner.cpp | 90 +++++++++++----------------
 1 file changed, 37 insertions(+), 53 deletions(-)

diff --git a/src/plugins/android/androidrunner.cpp b/src/plugins/android/androidrunner.cpp
index 81bea64acfd..0be297369ef 100644
--- a/src/plugins/android/androidrunner.cpp
+++ b/src/plugins/android/androidrunner.cpp
@@ -128,6 +128,21 @@ static const QString pidScript = QStringLiteral("for p in /proc/[0-9]*; "
                                                 "do cat <$p/cmdline && echo :${p##*/}; done");
 static const QString pidPollingScript = QStringLiteral("while true; do sleep 1; "
                                                        "cat /proc/%1/cmdline > /dev/null; done");
+
+static const QString regExpLogcat = QStringLiteral("[0-9\\-]*"  // date
+                                                  "\\s+"
+                                                  "[0-9\\-:.]*"// time
+                                                  "\\s*"
+                                                  "(\\d*)"     // pid           1. capture
+                                                  "\\s+"
+                                                  "\\d*"       // unknown
+                                                  "\\s+"
+                                                  "(\\w)"      // message type  2. capture
+                                                  "\\s+"
+                                                  "(.*): "     // source        3. capture
+                                                  "(.*)"       // message       4. capture
+                                                  "[\\n\\r]*"
+                                                 );
 static int APP_START_TIMEOUT = 45000;
 
 static bool isTimedOut(const chrono::high_resolution_clock::time_point &start,
@@ -199,8 +214,6 @@ public:
                         const QString &packageName, const QStringList &selector);
     ~AndroidRunnerWorker();
 
-    void init();
-
     void asyncStart(const QString &intentName, const QVector<QStringList> &adbCommands);
     void asyncStop(const QVector<QStringList> &adbCommands);
 
@@ -246,7 +259,6 @@ private:
     QString m_gdbserverPath;
     QString m_gdbserverSocket;
     QString m_adb;
-    bool m_isBusyBox = false;
     QStringList m_selector;
     QRegExp m_logCatRegExp;
     DebugHandShakeType m_handShakeMethod = SocketHandShake;
@@ -261,6 +273,7 @@ AndroidRunnerWorker::AndroidRunnerWorker(AndroidRunConfiguration *runConfig, Cor
     : m_adbLogcatProcess(nullptr, deleter)
     , m_psIsAlive(nullptr, deleter)
     , m_selector(selector)
+    , m_logCatRegExp(regExpLogcat)
     , m_packageName(packageName)
 {
     Debugger::DebuggerRunConfigurationAspect *aspect
@@ -328,41 +341,6 @@ AndroidRunnerWorker::~AndroidRunnerWorker()
         m_pidFinder.cancel();
 }
 
-// This is run from the worker thread.
-void AndroidRunnerWorker::init()
-{
-    QTC_ASSERT(!m_adbLogcatProcess, /**/);
-    m_adbLogcatProcess.reset(new QProcess);
-
-    // Detect busybox, as we need to pass -w to ps to get wide output.
-    Utils::SynchronousProcess psProc;
-    psProc.setTimeoutS(5);
-    Utils::SynchronousProcessResponse response = psProc.runBlocking(
-                m_adb, selector() << "shell" << "readlink" << "$(which ps)");
-    const QString which = response.allOutput();
-    m_isBusyBox = which.startsWith("busybox");
-
-    connect(m_adbLogcatProcess.get(), &QProcess::readyReadStandardOutput,
-            this, &AndroidRunnerWorker::logcatReadStandardOutput);
-    connect(m_adbLogcatProcess.get(), &QProcess::readyReadStandardError,
-            this, &AndroidRunnerWorker::logcatReadStandardError);
-
-    m_logCatRegExp = QRegExp(QLatin1String("[0-9\\-]*"  // date
-                                           "\\s+"
-                                           "[0-9\\-:.]*"// time
-                                           "\\s*"
-                                           "(\\d*)"     // pid           1. capture
-                                           "\\s+"
-                                           "\\d*"       // unknown
-                                           "\\s+"
-                                           "(\\w)"      // message type  2. capture
-                                           "\\s+"
-                                           "(.*): "     // source        3. capture
-                                           "(.*)"       // message       4. capture
-                                           "[\\n\\r]*"
-                                          ));
-}
-
 void AndroidRunnerWorker::forceStop()
 {
     runAdb(selector() << "shell" << "am" << "force-stop" << m_packageName, nullptr, 30);
@@ -383,8 +361,14 @@ void AndroidRunnerWorker::asyncStart(const QString &intentName,
 {
     forceStop();
 
-    // Its assumed that the device or avd serial returned by selector() is online.
-    m_adbLogcatProcess->start(m_adb, selector() << "logcat");
+    // Start the logcat process before app starts.
+    std::unique_ptr<QProcess, decltype(&deleter)> logcatProcess(new QProcess, deleter);
+    connect(logcatProcess.get(), &QProcess::readyReadStandardOutput,
+            this, &AndroidRunnerWorker::logcatReadStandardOutput);
+    connect(logcatProcess.get(), &QProcess::readyReadStandardError,
+            this, &AndroidRunnerWorker::logcatReadStandardError);
+    // Its assumed that the device or avd returned by selector() is online.
+    logcatProcess->start(m_adb, selector() << "logcat");
 
     QString errorMessage;
 
@@ -481,9 +465,6 @@ void AndroidRunnerWorker::asyncStart(const QString &intentName,
                 break;
             }
 
-            if (!wasSuccess)
-                emit remoteProcessFinished(tr("Failed to contact debugging port."));
-
             if (!m_customPort) {
                 // increment running port to avoid clash when using multiple
                 // debug sessions at the same time
@@ -492,6 +473,11 @@ void AndroidRunnerWorker::asyncStart(const QString &intentName,
                 if (m_socketHandShakePort == MAX_SOCKET_HANDSHAKE_PORT)
                     m_socketHandShakePort = MIN_SOCKET_HANDSHAKE_PORT;
             }
+
+            if (!wasSuccess) {
+                emit remoteProcessFinished(tr("Failed to contact debugging port."));
+                return;
+            }
         } else {
             // Handling ping.
             for (int i = 0; ; ++i) {
@@ -517,6 +503,9 @@ void AndroidRunnerWorker::asyncStart(const QString &intentName,
         }
 
     }
+
+    QTC_ASSERT(!m_adbLogcatProcess, /**/);
+    m_adbLogcatProcess = std::move(logcatProcess);
     m_pidFinder = Utils::onResultReady(Utils::runAsync(&findProcessPID, m_adb, selector(),
                                                        m_packageName),
                                        bind(&AndroidRunnerWorker::onProcessIdChanged, this, _1));
@@ -578,16 +567,11 @@ void AndroidRunnerWorker::asyncStop(const QVector<QStringList> &adbCommands)
     if (!m_pidFinder.isFinished())
         m_pidFinder.cancel();
 
-    m_adbLogcatProcess.reset();
-    m_psIsAlive.reset();
-
     if (m_processPID != -1) {
         forceStop();
     }
     foreach (const QStringList &entry, adbCommands)
         runAdb(selector() << entry);
-
-    emit remoteProcessFinished(QLatin1String("\n\n") + tr("\"%1\" terminated.").arg(m_packageName));
 }
 
 void AndroidRunnerWorker::setAdbParameters(const QString &packageName, const QStringList &selector)
@@ -645,9 +629,11 @@ void AndroidRunnerWorker::onProcessIdChanged(qint64 pid)
     QTC_ASSERT(QThread::currentThread() == thread(), return);
     m_processPID = pid;
     if (m_processPID == -1) {
-            emit remoteProcessFinished(QLatin1String("\n\n") + tr("\"%1\" died.")
-                                       .arg(m_packageName));
-            m_psIsAlive.reset();
+        emit remoteProcessFinished(QLatin1String("\n\n") + tr("\"%1\" died.")
+                                   .arg(m_packageName));
+        // App died/killed. Reset log and monitor processes.
+        m_adbLogcatProcess.reset();
+        m_psIsAlive.reset();
     } else {
         if (m_useCppDebugger) {
             // This will be funneled to the engine to actually start and attach
@@ -720,8 +706,6 @@ AndroidRunner::AndroidRunner(QObject *parent, AndroidRunConfiguration *runConfig
                 AndroidDeviceInfo::adbSelector(m_androidRunnable.deviceSerialNumber)));
     m_worker->moveToThread(&m_thread);
 
-    connect(&m_thread, &QThread::started, m_worker.data(), &AndroidRunnerWorker::init);
-
     connect(this, &AndroidRunner::asyncStart, m_worker.data(), &AndroidRunnerWorker::asyncStart);
     connect(this, &AndroidRunner::asyncStop, m_worker.data(), &AndroidRunnerWorker::asyncStop);
     connect(this, &AndroidRunner::adbParametersChanged,
-- 
GitLab