diff --git a/src/network/kernel/qnetconmonitor_darwin.mm b/src/network/kernel/qnetconmonitor_darwin.mm index b94cbabab1a..0bb4329cac7 100644 --- a/src/network/kernel/qnetconmonitor_darwin.mm +++ b/src/network/kernel/qnetconmonitor_darwin.mm @@ -11,6 +11,9 @@ #include +#include +#include + #include QT_BEGIN_NAMESPACE @@ -85,6 +88,10 @@ public: SCNetworkReachabilityFlags state = kSCNetworkReachabilityFlagsIsLocalAddress; bool scheduled = false; + QWaitCondition refCounterWaitCondition; + QMutex refCounterMutex; + quint32 refCounter = 0; + void updateState(SCNetworkReachabilityFlags newState); void reset(); bool isReachable() const; @@ -92,7 +99,30 @@ public: bool isWwan() const; #endif + void retain() + { + QMutexLocker locker(&refCounterMutex); + ++refCounter; + } + + void release() + { + QMutexLocker locker(&refCounterMutex); + if (--refCounter == 0) + refCounterWaitCondition.wakeAll(); + } + + void waitForRefCountZero() + { + QMutexLocker locker(&refCounterMutex); + while (refCounter > 0) { + refCounterWaitCondition.wait(&refCounterMutex); + } + } + static void probeCallback(SCNetworkReachabilityRef probe, SCNetworkReachabilityFlags flags, void *info); + static const void *retainInfo(const void* info); + static void releaseInfo(const void* info); Q_DECLARE_PUBLIC(QNetworkConnectionMonitor) }; @@ -130,6 +160,7 @@ void QNetworkConnectionMonitorPrivate::reset() state = kSCNetworkReachabilityFlagsIsLocalAddress; scheduled = false; + waitForRefCountZero(); } bool QNetworkConnectionMonitorPrivate::isReachable() const @@ -154,6 +185,19 @@ void QNetworkConnectionMonitorPrivate::probeCallback(SCNetworkReachabilityRef pr monitorPrivate->updateState(flags); } +const void *QNetworkConnectionMonitorPrivate::retainInfo(const void *info) +{ + auto monitorPrivate = static_cast(const_cast(info)); + monitorPrivate->retain(); + return info; +} + +void QNetworkConnectionMonitorPrivate::releaseInfo(const void *info) +{ + auto monitorPrivate = static_cast(const_cast(info)); + monitorPrivate->release(); +} + QNetworkConnectionMonitor::QNetworkConnectionMonitor() : QObject(*new QNetworkConnectionMonitorPrivate) { @@ -235,6 +279,8 @@ bool QNetworkConnectionMonitor::startMonitoring() SCNetworkReachabilityContext context = {}; context.info = d; + context.retain = QNetworkConnectionMonitorPrivate::retainInfo; + context.release = QNetworkConnectionMonitorPrivate::releaseInfo; if (!SCNetworkReachabilitySetCallback(d->probe, QNetworkConnectionMonitorPrivate::probeCallback, &context)) { qCWarning(lcNetMon, "Failed to set a reachability callback"); return false;