Guard coroutine calls

Fixes https://invent.kde.org/plasma/plasma-mobile/-/issues/480

This ensures that coroutines are properly guarded against object
deletion.
This commit is contained in:
Devin Lin 2026-01-07 21:02:02 -05:00
parent 5b48cc9cc9
commit cd7dd7c8e5
5 changed files with 71 additions and 24 deletions

View file

@ -3,6 +3,8 @@
#include "vibrationmanager.h" #include "vibrationmanager.h"
#include <QPointer>
VibrationManager::VibrationManager(QObject *parent) VibrationManager::VibrationManager(QObject *parent)
: QObject{parent} : QObject{parent}
{ {
@ -21,8 +23,14 @@ QCoro::Task<void> VibrationManager::vibrateTask(int durationMs)
const QString appId = QStringLiteral("org.kde.plasmashell"); const QString appId = QStringLiteral("org.kde.plasmashell");
const VibrationEvent event{1.0, static_cast<quint32>(durationMs)}; const VibrationEvent event{1.0, static_cast<quint32>(durationMs)};
const VibrationEventList pattern = {event}; const VibrationEventList pattern = {event};
QPointer<VibrationManager> guard(this);
QDBusPendingReply<bool> reply = co_await m_interface->Vibrate(appId, pattern); QDBusPendingReply<bool> reply = co_await m_interface->Vibrate(appId, pattern);
if (!guard) {
co_return;
}
if (!reply.isValid() || !reply.value()) { if (!reply.isValid() || !reply.value()) {
qWarning() << "feedbackd vibration failed"; qWarning() << "feedbackd vibration failed";
} }

View file

@ -9,6 +9,7 @@
#include <NetworkManagerQt/Settings> #include <NetworkManagerQt/Settings>
#include <NetworkManagerQt/Utils> #include <NetworkManagerQt/Utils>
#include <QDBusReply> #include <QDBusReply>
#include <QPointer>
#include <KUser> #include <KUser>
@ -226,7 +227,13 @@ QCoro::Task<void> SignalIndicator::activateProfile(const QString &connectionUni)
// activate connection manually // activate connection manually
// despite the documentation saying otherwise, activateConnection seems to need the DBus path, not uuid of the connection // despite the documentation saying otherwise, activateConnection seems to need the DBus path, not uuid of the connection
QPointer<SignalIndicator> guard(this);
QDBusReply<QDBusObjectPath> reply = co_await NetworkManager::activateConnection(con->path(), m_nmModem->uni(), {}); QDBusReply<QDBusObjectPath> reply = co_await NetworkManager::activateConnection(con->path(), m_nmModem->uni(), {});
if (!guard) {
co_return;
}
if (!reply.isValid()) { if (!reply.isValid()) {
qWarning() << QStringLiteral("Error activating connection:") << reply.error().message(); qWarning() << QStringLiteral("Error activating connection:") << reply.error().message();
co_return; co_return;
@ -255,7 +262,13 @@ QCoro::Task<void> SignalIndicator::addProfile(const QString &name, const QString
gsmSetting->setInitialized(true); gsmSetting->setInitialized(true);
QPointer<SignalIndicator> guard(this);
QDBusReply<QDBusObjectPath> reply = co_await NetworkManager::addAndActivateConnection(settings->toMap(), m_nmModem->uni(), {}); QDBusReply<QDBusObjectPath> reply = co_await NetworkManager::addAndActivateConnection(settings->toMap(), m_nmModem->uni(), {});
if (!guard) {
co_return;
}
if (!reply.isValid()) { if (!reply.isValid()) {
qWarning() << "Error adding connection:" << reply.error().message(); qWarning() << "Error adding connection:" << reply.error().message();
} else { } else {
@ -271,7 +284,13 @@ QCoro::Task<void> SignalIndicator::removeProfile(const QString &connectionUni)
co_return; co_return;
} }
QPointer<SignalIndicator> guard(this);
QDBusPendingReply reply = co_await con->remove(); QDBusPendingReply reply = co_await con->remove();
if (!guard) {
co_return;
}
if (!reply.isValid()) { if (!reply.isValid()) {
qWarning() << "Error removing connection" << reply.error().message(); qWarning() << "Error removing connection" << reply.error().message();
} }
@ -307,7 +326,13 @@ QCoro::Task<void> SignalIndicator::updateProfile(const QString &connectionUni,
gsmSetting->setInitialized(true); gsmSetting->setInitialized(true);
QPointer<SignalIndicator> guard(this);
QDBusPendingReply reply = co_await con->update(conSettings->toMap()); QDBusPendingReply reply = co_await con->update(conSettings->toMap());
if (!guard) {
co_return;
}
if (!reply.isValid()) { if (!reply.isValid()) {
qWarning() << "Error updating connection settings for" << connectionUni << ":" << reply.error().message() << "."; qWarning() << "Error updating connection settings for" << connectionUni << ":" << reply.error().message() << ".";
} else { } else {

View file

@ -9,6 +9,7 @@
#include <QDBusInterface> #include <QDBusInterface>
#include <QDBusMessage> #include <QDBusMessage>
#include <QDBusReply> #include <QDBusReply>
#include <QPointer>
#include <KLocalizedString> #include <KLocalizedString>
#include <KPackage/Package> #include <KPackage/Package>
@ -171,7 +172,13 @@ QCoro::Task<void> WallpaperPlugin::setHomescreenWallpaper(const QString &path)
for (uint screen = 0; screen < qApp->screens().size(); screen++) { for (uint screen = 0; screen < qApp->screens().size(); screen++) {
message.setArguments({"org.kde.image", QVariantMap{{"Image", path}}, screen}); message.setArguments({"org.kde.image", QVariantMap{{"Image", path}}, screen});
QPointer<WallpaperPlugin> guard(this);
const QDBusReply<void> reply = co_await QDBusConnection::sessionBus().asyncCall(message); const QDBusReply<void> reply = co_await QDBusConnection::sessionBus().asyncCall(message);
if (!guard) {
co_return;
}
if (!reply.isValid()) { if (!reply.isValid()) {
qWarning() << "Failed to set wallpaper for screen" << screen << ":" << reply.error(); qWarning() << "Failed to set wallpaper for screen" << screen << ":" << reply.error();
} }
@ -210,7 +217,13 @@ QCoro::Task<void> WallpaperPlugin::loadHomescreenSettings()
QLatin1String("wallpaper")); QLatin1String("wallpaper"));
message.setArguments({(uint)0}); // assume wallpaper on first screen message.setArguments({(uint)0}); // assume wallpaper on first screen
QPointer<WallpaperPlugin> guard(this);
QDBusReply<QVariantMap> reply = co_await QDBusConnection::sessionBus().asyncCall(message); QDBusReply<QVariantMap> reply = co_await QDBusConnection::sessionBus().asyncCall(message);
if (!guard) {
co_return;
}
if (!reply.isValid()) { if (!reply.isValid()) {
qWarning() << "unable to load homescreen wallpaper settings:" << reply.error(); qWarning() << "unable to load homescreen wallpaper settings:" << reply.error();
co_return; co_return;
@ -317,7 +330,13 @@ QCoro::Task<void> WallpaperPlugin::saveHomescreenSettings()
for (uint screen = 0; screen < qApp->screens().size(); screen++) { for (uint screen = 0; screen < qApp->screens().size(); screen++) {
QList<QVariant> args = {m_homescreenWallpaperPlugin, params, screen}; QList<QVariant> args = {m_homescreenWallpaperPlugin, params, screen};
QPointer<WallpaperPlugin> guard(this);
const QDBusReply<void> response = co_await iface->asyncCallWithArgumentList(QStringLiteral("setWallpaper"), args); const QDBusReply<void> response = co_await iface->asyncCallWithArgumentList(QStringLiteral("setWallpaper"), args);
if (!guard) {
co_return;
}
if (!response.isValid()) { if (!response.isValid()) {
qWarning() << "Failed to set wallpaper:" << response.error(); qWarning() << "Failed to set wallpaper:" << response.error();
} }

View file

@ -133,8 +133,7 @@ WaydroidApplicationListModel *WaydroidDBusClient::applicationListModel() const
QCoro::Task<void> WaydroidDBusClient::setMultiWindowsTask(const bool multiWindows) QCoro::Task<void> WaydroidDBusClient::setMultiWindowsTask(const bool multiWindows)
{ {
auto pendingReply = m_interface->setMultiWindows(multiWindows); co_await m_interface->setMultiWindows(multiWindows);
co_await pendingReply;
} }
QCoro::QmlTask WaydroidDBusClient::setMultiWindows(const bool multiWindows) QCoro::QmlTask WaydroidDBusClient::setMultiWindows(const bool multiWindows)
@ -149,8 +148,7 @@ bool WaydroidDBusClient::multiWindows() const
QCoro::Task<void> WaydroidDBusClient::setSuspendTask(const bool suspend) QCoro::Task<void> WaydroidDBusClient::setSuspendTask(const bool suspend)
{ {
auto pendingReply = m_interface->setSuspend(suspend); co_await m_interface->setSuspend(suspend);
co_await pendingReply;
} }
QCoro::QmlTask WaydroidDBusClient::setSuspend(const bool suspend) QCoro::QmlTask WaydroidDBusClient::setSuspend(const bool suspend)
@ -165,8 +163,7 @@ bool WaydroidDBusClient::suspend() const
QCoro::Task<void> WaydroidDBusClient::setUeventTask(const bool uevent) QCoro::Task<void> WaydroidDBusClient::setUeventTask(const bool uevent)
{ {
auto pendingReply = m_interface->setUevent(uevent); co_await m_interface->setUevent(uevent);
co_await pendingReply;
} }
QCoro::QmlTask WaydroidDBusClient::setUevent(const bool uevent) QCoro::QmlTask WaydroidDBusClient::setUevent(const bool uevent)
@ -176,8 +173,7 @@ QCoro::QmlTask WaydroidDBusClient::setUevent(const bool uevent)
QCoro::Task<void> WaydroidDBusClient::refreshSessionInfoTask() QCoro::Task<void> WaydroidDBusClient::refreshSessionInfoTask()
{ {
auto pendingReply = m_interface->refreshSessionInfo(); co_await m_interface->refreshSessionInfo();
co_await pendingReply;
} }
QCoro::QmlTask WaydroidDBusClient::refreshSessionInfo() QCoro::QmlTask WaydroidDBusClient::refreshSessionInfo()
@ -187,8 +183,7 @@ QCoro::QmlTask WaydroidDBusClient::refreshSessionInfo()
QCoro::Task<void> WaydroidDBusClient::refreshAndroidIdTask() QCoro::Task<void> WaydroidDBusClient::refreshAndroidIdTask()
{ {
auto pendingReply = m_interface->refreshAndroidId(); co_await m_interface->refreshAndroidId();
co_await pendingReply;
} }
QCoro::QmlTask WaydroidDBusClient::refreshAndroidId() QCoro::QmlTask WaydroidDBusClient::refreshAndroidId()
@ -198,8 +193,7 @@ QCoro::QmlTask WaydroidDBusClient::refreshAndroidId()
QCoro::Task<void> WaydroidDBusClient::refreshApplicationsTask() QCoro::Task<void> WaydroidDBusClient::refreshApplicationsTask()
{ {
auto pendingReply = m_interface->refreshApplications(); co_await m_interface->refreshApplications();
co_await pendingReply;
} }
QCoro::QmlTask WaydroidDBusClient::refreshApplications() QCoro::QmlTask WaydroidDBusClient::refreshApplications()
@ -214,8 +208,7 @@ bool WaydroidDBusClient::uevent() const
QCoro::Task<void> WaydroidDBusClient::initializeTask(const SystemType systemType, const RomType romType, const bool forced) QCoro::Task<void> WaydroidDBusClient::initializeTask(const SystemType systemType, const RomType romType, const bool forced)
{ {
auto pendingReply = m_interface->initialize(systemType, romType, forced); co_await m_interface->initialize(systemType, romType, forced);
co_await pendingReply;
} }
QCoro::QmlTask WaydroidDBusClient::initialize(const SystemType systemType, const RomType romType, const bool forced) QCoro::QmlTask WaydroidDBusClient::initialize(const SystemType systemType, const RomType romType, const bool forced)
@ -225,8 +218,7 @@ QCoro::QmlTask WaydroidDBusClient::initialize(const SystemType systemType, const
QCoro::Task<void> WaydroidDBusClient::startSessionTask() QCoro::Task<void> WaydroidDBusClient::startSessionTask()
{ {
auto pendingReply = m_interface->startSession(); co_await m_interface->startSession();
co_await pendingReply;
} }
QCoro::QmlTask WaydroidDBusClient::startSession() QCoro::QmlTask WaydroidDBusClient::startSession()
@ -236,8 +228,7 @@ QCoro::QmlTask WaydroidDBusClient::startSession()
QCoro::Task<void> WaydroidDBusClient::stopSessionTask() QCoro::Task<void> WaydroidDBusClient::stopSessionTask()
{ {
auto pendingReply = m_interface->stopSession(); co_await m_interface->stopSession();
co_await pendingReply;
} }
QCoro::QmlTask WaydroidDBusClient::stopSession() QCoro::QmlTask WaydroidDBusClient::stopSession()
@ -247,8 +238,7 @@ QCoro::QmlTask WaydroidDBusClient::stopSession()
QCoro::Task<void> WaydroidDBusClient::resetWaydroidTask() QCoro::Task<void> WaydroidDBusClient::resetWaydroidTask()
{ {
auto pendingReply = m_interface->resetWaydroid(); co_await m_interface->resetWaydroid();
co_await pendingReply;
} }
QCoro::QmlTask WaydroidDBusClient::resetWaydroid() QCoro::QmlTask WaydroidDBusClient::resetWaydroid()
@ -258,8 +248,7 @@ QCoro::QmlTask WaydroidDBusClient::resetWaydroid()
QCoro::Task<void> WaydroidDBusClient::installApkTask(const QString apkFile) QCoro::Task<void> WaydroidDBusClient::installApkTask(const QString apkFile)
{ {
auto pendingReply = m_interface->installApk(apkFile); co_await m_interface->installApk(apkFile);
co_await pendingReply;
} }
QCoro::QmlTask WaydroidDBusClient::installApk(const QString apkFile) QCoro::QmlTask WaydroidDBusClient::installApk(const QString apkFile)
@ -269,8 +258,7 @@ QCoro::QmlTask WaydroidDBusClient::installApk(const QString apkFile)
QCoro::Task<void> WaydroidDBusClient::deleteApplicationTask(const QString appId) QCoro::Task<void> WaydroidDBusClient::deleteApplicationTask(const QString appId)
{ {
auto pendingReply = m_interface->deleteApplication(appId); co_await m_interface->deleteApplication(appId);
co_await pendingReply;
} }
QCoro::QmlTask WaydroidDBusClient::deleteApplication(const QString appId) QCoro::QmlTask WaydroidDBusClient::deleteApplication(const QString appId)

View file

@ -13,6 +13,7 @@
#include <QDomElement> #include <QDomElement>
#include <QFile> #include <QFile>
#include <QLoggingCategory> #include <QLoggingCategory>
#include <QPointer>
#include <QStandardPaths> #include <QStandardPaths>
#include <NetworkManagerQt/CdmaSetting> #include <NetworkManagerQt/CdmaSetting>
@ -106,7 +107,13 @@ QCoro::Task<void> AutoDetectAPN::checkAndAddAutodetectedAPN()
ipv6Setting->setInitialized(true); ipv6Setting->setInitialized(true);
} }
QPointer<AutoDetectAPN> guard(this);
QDBusReply<QDBusObjectPath> reply = co_await NetworkManager::addAndActivateConnection(settings->toMap(), nmModem->uni(), ""); QDBusReply<QDBusObjectPath> reply = co_await NetworkManager::addAndActivateConnection(settings->toMap(), nmModem->uni(), "");
if (!guard) {
co_return;
}
if (!reply.isValid()) { if (!reply.isValid()) {
qCWarning(LOGGING_CATEGORY) << "Error adding autodetected connection:" << reply.error().message(); qCWarning(LOGGING_CATEGORY) << "Error adding autodetected connection:" << reply.error().message();
} else { } else {