forked from qt-creator/qt-creator
Android: Synchronize startAvd()'s future
This change fixes a possible deadlock on Creator shutdown after clicking "Start AVD" button from the Android device settings dialog, and quickly closing the started emulator window, the settings dialog and Creator (within 2 seconds). In case of no synchronization we may be starting new processes in separate thread after the QApplication has already been destroyed. Blocking run of processes requires constructing an event loop, which ends up with the following warnings (and a deadlock): "QEventLoop: Cannot be used without QApplication" "QObject::setParent: Cannot set parent, new parent is in a different thread". Add returned future to the global future synchronizer. Avoid long synchronization of startAvd() on shutdown by adding an optional future argument to the startAvd() and pass it to the waitForAvd(). Otherwise, we would need to wait up to 2 minutes for synchronization to finish. Change-Id: Ia1d71d309cb2dcdb5e31decfdfdea6df9a117ed5 Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
@@ -20,10 +20,10 @@ namespace Android::Internal::AndroidAvdManager {
|
||||
|
||||
static Q_LOGGING_CATEGORY(avdManagerLog, "qtc.android.avdManager", QtWarningMsg)
|
||||
|
||||
QString startAvd(const QString &name)
|
||||
QString startAvd(const QString &name, const std::optional<QFuture<void>> &future)
|
||||
{
|
||||
if (!findAvd(name).isEmpty() || startAvdAsync(name))
|
||||
return waitForAvd(name);
|
||||
return waitForAvd(name, future);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
|
||||
namespace Android::Internal::AndroidAvdManager {
|
||||
|
||||
QString startAvd(const QString &name);
|
||||
QString startAvd(const QString &name, const std::optional<QFuture<void>> &future = {});
|
||||
bool startAvdAsync(const QString &avdName);
|
||||
QString findAvd(const QString &avdName);
|
||||
QString waitForAvd(const QString &avdName, const std::optional<QFuture<void>> &future = {});
|
||||
|
@@ -111,15 +111,14 @@ static void startAvd(const IDevice::Ptr &device, QWidget *parent)
|
||||
const AndroidDevice *androidDev = static_cast<const AndroidDevice *>(device.get());
|
||||
const QString name = androidDev->avdName();
|
||||
qCDebug(androidDeviceLog, "Starting Android AVD id \"%s\".", qPrintable(name));
|
||||
auto future = Utils::asyncRun([name, device] {
|
||||
const QString serialNumber = AndroidAvdManager::startAvd(name);
|
||||
Utils::futureSynchronizer()->addFuture(Utils::asyncRun([name, device](QPromise<void> &promise) {
|
||||
const QString serialNumber = AndroidAvdManager::startAvd(name, promise.future());
|
||||
// Mark the AVD as ReadyToUse once we know it's started
|
||||
if (!serialNumber.isEmpty()) {
|
||||
DeviceManager *const devMgr = DeviceManager::instance();
|
||||
devMgr->setDeviceState(device->id(), IDevice::DeviceReadyToUse);
|
||||
}
|
||||
});
|
||||
// TODO: use future!
|
||||
}));
|
||||
}
|
||||
|
||||
static void setEmulatorArguments(QWidget *parent)
|
||||
|
Reference in New Issue
Block a user