From a78f42a19969ab19cfc3be2dde87b58081589ac7 Mon Sep 17 00:00:00 2001 From: NickVs2015 Date: Fri, 3 Apr 2026 20:30:08 +0300 Subject: [PATCH] fix: make dbus async --- .../platforms/linux/daemon/dnsutilslinux.cpp | 96 +++++++++++++++---- client/platforms/linux/daemon/dnsutilslinux.h | 12 ++- 2 files changed, 87 insertions(+), 21 deletions(-) diff --git a/client/platforms/linux/daemon/dnsutilslinux.cpp b/client/platforms/linux/daemon/dnsutilslinux.cpp index cc47202b5..141dcccb2 100644 --- a/client/platforms/linux/daemon/dnsutilslinux.cpp +++ b/client/platforms/linux/daemon/dnsutilslinux.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include "leakdetector.h" @@ -27,24 +28,53 @@ DnsUtilsLinux::DnsUtilsLinux(QObject* parent) : DnsUtils(parent) { logger.debug() << "DnsUtilsLinux created."; QDBusConnection conn = QDBusConnection::systemBus(); - m_resolver = new QDBusInterface(DBUS_RESOLVE_SERVICE, DBUS_RESOLVE_PATH, - DBUS_RESOLVE_MANAGER, conn, this); + auto* watcher = new QDBusServiceWatcher( + DBUS_RESOLVE_SERVICE, conn, + QDBusServiceWatcher::WatchForRegistration | + QDBusServiceWatcher::WatchForUnregistration, this); + + connect(watcher, &QDBusServiceWatcher::serviceRegistered, + this, &DnsUtilsLinux::onResolverRegistered); + connect(watcher, &QDBusServiceWatcher::serviceUnregistered, + this, &DnsUtilsLinux::onResolverUnregistered); + + if (conn.interface()->isServiceRegistered(DBUS_RESOLVE_SERVICE)) { + onResolverRegistered(); + } +} + +void DnsUtilsLinux::onResolverRegistered() { + m_resolver.reset(new QDBusInterface(DBUS_RESOLVE_SERVICE, DBUS_RESOLVE_PATH, + DBUS_RESOLVE_MANAGER, + QDBusConnection::systemBus())); + logger.debug() << "systemd-resolved available, DNS resolver initialized"; + + if (!m_pendingIfname.isEmpty()) { + logger.debug() << "Re-applying DNS configuration for" << m_pendingIfname; + updateResolvers(m_pendingIfname, m_pendingResolvers); + } +} + +void DnsUtilsLinux::onResolverUnregistered() { + logger.debug() << "systemd-resolved disappeared, dropping DNS resolver"; + m_resolver.reset(); } DnsUtilsLinux::~DnsUtilsLinux() { MZ_COUNT_DTOR(DnsUtilsLinux); - for (auto iterator = m_linkDomains.constBegin(); - iterator != m_linkDomains.constEnd(); ++iterator) { - QList argumentList; - argumentList << QVariant::fromValue(iterator.key()); - argumentList << QVariant::fromValue(iterator.value()); - m_resolver->asyncCallWithArgumentList(QStringLiteral("SetLinkDomains"), - argumentList); - } - - if (m_ifindex > 0) { - m_resolver->asyncCall(QStringLiteral("RevertLink"), m_ifindex); + if (m_resolver) { + for (auto iterator = m_linkDomains.constBegin(); + iterator != m_linkDomains.constEnd(); ++iterator) { + QList argumentList; + argumentList << QVariant::fromValue(iterator.key()); + argumentList << QVariant::fromValue(iterator.value()); + m_resolver->asyncCallWithArgumentList(QStringLiteral("SetLinkDomains"), + argumentList); + } + if (m_ifindex > 0) { + m_resolver->asyncCall(QStringLiteral("RevertLink"), m_ifindex); + } } logger.debug() << "DnsUtilsLinux destroyed."; @@ -58,13 +88,25 @@ bool DnsUtilsLinux::updateResolvers(const QString& ifname, return false; } + m_pendingIfname = ifname; + m_pendingResolvers = resolvers; + + if (!m_resolver) { + logger.debug() << "systemd-resolved not ready, queuing DNS configuration"; + return true; + } + setLinkDNS(m_ifindex, resolvers); setLinkDefaultRoute(m_ifindex, true); + setLinkDomains(m_ifindex, {DnsLinkDomain(".", true)}); updateLinkDomains(); return true; } bool DnsUtilsLinux::restoreResolvers() { + m_pendingIfname.clear(); + m_pendingResolvers.clear(); + for (auto iterator = m_linkDomains.constBegin(); iterator != m_linkDomains.constEnd(); ++iterator) { setLinkDomains(iterator.key(), iterator.value()); @@ -72,7 +114,7 @@ bool DnsUtilsLinux::restoreResolvers() { m_linkDomains.clear(); /* Revert the VPN interface's DNS configuration */ - if (m_ifindex > 0) { + if (m_ifindex > 0 && m_resolver) { QList argumentList = {QVariant::fromValue(m_ifindex)}; QDBusPendingReply<> reply = m_resolver->asyncCallWithArgumentList( QStringLiteral("RevertLink"), argumentList); @@ -90,13 +132,14 @@ bool DnsUtilsLinux::restoreResolvers() { void DnsUtilsLinux::dnsCallCompleted(QDBusPendingCallWatcher* call) { QDBusPendingReply<> reply = *call; if (reply.isError()) { - logger.error() << "Error received from the DBus service"; + logger.debug() << "DBus call failed (may be transient after systemd-resolved restart)"; } delete call; } void DnsUtilsLinux::setLinkDNS(int ifindex, const QList& resolvers) { + if (!m_resolver) return; QList resolverList; char ifnamebuf[IF_NAMESIZE]; const char* ifname = if_indextoname(ifindex, ifnamebuf); @@ -121,6 +164,7 @@ void DnsUtilsLinux::setLinkDNS(int ifindex, void DnsUtilsLinux::setLinkDomains(int ifindex, const QList& domains) { + if (!m_resolver) return; char ifnamebuf[IF_NAMESIZE]; const char* ifname = if_indextoname(ifindex, ifnamebuf); if (ifname) { @@ -144,6 +188,7 @@ void DnsUtilsLinux::setLinkDomains(int ifindex, } void DnsUtilsLinux::setLinkDefaultRoute(int ifindex, bool enable) { + if (!m_resolver) return; QList argumentList; argumentList << QVariant::fromValue(ifindex); argumentList << QVariant::fromValue(enable); @@ -156,6 +201,7 @@ void DnsUtilsLinux::setLinkDefaultRoute(int ifindex, bool enable) { } void DnsUtilsLinux::updateLinkDomains() { + if (!m_resolver) return; /* Get the list of search domains, and remove any others that might conspire * to satisfy DNS resolution. Unfortunately, this is a pain because Qt doesn't * seem to be able to demarshall complex property types. @@ -174,11 +220,20 @@ void DnsUtilsLinux::updateLinkDomains() { void DnsUtilsLinux::dnsDomainsReceived(QDBusPendingCallWatcher* call) { QDBusPendingReply reply = *call; + call->deleteLater(); if (reply.isError()) { - logger.error() << "Error retrieving the DNS domains from the DBus service"; - delete call; + // systemd-resolved may still be starting up after a restart — retry a few times + if (m_ifindex > 0 && m_domainRetries++ < 5) { + logger.debug() << "systemd-resolved not ready yet, retrying DNS setup (" + << m_domainRetries << "/5)"; + QTimer::singleShot(500, this, &DnsUtilsLinux::updateLinkDomains); + } else { + logger.warning() << "Failed to configure DNS after 5 retries"; + m_domainRetries = 0; + } return; } + m_domainRetries = 0; /* Update the state of the DNS domains */ m_linkDomains.clear(); @@ -204,9 +259,10 @@ void DnsUtilsLinux::dnsDomainsReceived(QDBusPendingCallWatcher* call) { } /* Add a root search domain for the new interface. */ - QList newlist = {root}; - setLinkDomains(m_ifindex, newlist); - delete call; + if (m_ifindex > 0) { + QList newlist = {root}; + setLinkDomains(m_ifindex, newlist); + } } static DnsMetatypeRegistrationProxy s_dnsMetatypeProxy; diff --git a/client/platforms/linux/daemon/dnsutilslinux.h b/client/platforms/linux/daemon/dnsutilslinux.h index e4bbd2734..20ba274f2 100644 --- a/client/platforms/linux/daemon/dnsutilslinux.h +++ b/client/platforms/linux/daemon/dnsutilslinux.h @@ -6,7 +6,12 @@ #define DNSUTILSLINUX_H #include +#include #include +#include +#include +#include +#include #include "daemon/dnsutils.h" #include "dbustypeslinux.h" @@ -29,13 +34,18 @@ class DnsUtilsLinux final : public DnsUtils { void updateLinkDomains(); private slots: + void onResolverRegistered(); + void onResolverUnregistered(); void dnsCallCompleted(QDBusPendingCallWatcher*); void dnsDomainsReceived(QDBusPendingCallWatcher*); private: int m_ifindex = 0; + int m_domainRetries = 0; QMap m_linkDomains; - QDBusInterface* m_resolver = nullptr; + QScopedPointer m_resolver; + QString m_pendingIfname; + QList m_pendingResolvers; }; #endif // DNSUTILSLINUX_H