From ac45c694f3b08fbd458babe51cb14ae6cf5c8345 Mon Sep 17 00:00:00 2001 From: Thad House Date: Fri, 6 Feb 2026 21:37:11 -0800 Subject: [PATCH] [wpinet] Fix windows mDNS announcer long startup times (#8604) The existing code takes 750ms to start per resolver. This is too long, especially in mrccomm where we start 4 on initialize, and 3 any time the team number changes. Solve this by handling the async setup more correctly. Assuming it returns pending, we're assuming the announcer is good. Then on stop(), we cancel the register in case its still pending, wait for the callback, and then deregister. --- .../windows/MulticastServiceAnnouncer.cpp | 50 +++++++++++-------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/wpinet/src/main/native/windows/MulticastServiceAnnouncer.cpp b/wpinet/src/main/native/windows/MulticastServiceAnnouncer.cpp index 120816234e..956b2ced18 100644 --- a/wpinet/src/main/native/windows/MulticastServiceAnnouncer.cpp +++ b/wpinet/src/main/native/windows/MulticastServiceAnnouncer.cpp @@ -28,7 +28,8 @@ using namespace wpi::net; struct ImplBase { PDNS_SERVICE_INSTANCE serviceInstance = nullptr; - HANDLE event = nullptr; + DNS_SERVICE_CANCEL serviceCancel; + HANDLE registerEvent = nullptr; }; struct MulticastServiceAnnouncer::Impl : ImplBase { @@ -132,11 +133,11 @@ bool MulticastServiceAnnouncer::HasImplementation() const { static void WINAPI DnsServiceRegisterCallback(DWORD /*Status*/, PVOID pQueryContext, PDNS_SERVICE_INSTANCE pInstance) { - ImplBase* impl = reinterpret_cast(pQueryContext); - - impl->serviceInstance = pInstance; - - SetEvent(impl->event); + HANDLE registerEvent = reinterpret_cast(pQueryContext); + if (pInstance != nullptr) { + DnsServiceFreeInstance(pInstance); + } + SetEvent(registerEvent); } void MulticastServiceAnnouncer::Start() { @@ -153,34 +154,35 @@ void MulticastServiceAnnouncer::Start() { } DNS_SERVICE_REGISTER_REQUEST registerRequest = {}; - registerRequest.pQueryContext = static_cast(pImpl.get()); + std::memset(&pImpl->serviceCancel, 0, sizeof(DNS_SERVICE_CANCEL)); + pImpl->registerEvent = CreateEvent(NULL, true, false, NULL); + registerRequest.pQueryContext = pImpl->registerEvent; registerRequest.pRegisterCompletionCallback = DnsServiceRegisterCallback; registerRequest.Version = DNS_QUERY_REQUEST_VERSION1; registerRequest.unicastEnabled = false; registerRequest.pServiceInstance = serviceInst; registerRequest.InterfaceIndex = 0; - pImpl->event = CreateEvent(NULL, true, false, NULL); - - if (DnsServiceRegister(®isterRequest, nullptr) == DNS_REQUEST_PENDING) { - WaitForSingleObject(pImpl->event, INFINITE); + if (DnsServiceRegister(®isterRequest, &pImpl->serviceCancel) != + DNS_REQUEST_PENDING) { + DnsServiceFreeInstance(serviceInst); + CloseHandle(pImpl->registerEvent); + pImpl->registerEvent = nullptr; + return; } - DnsServiceFreeInstance(serviceInst); - CloseHandle(pImpl->event); - pImpl->event = nullptr; + pImpl->serviceInstance = serviceInst; } static void WINAPI DnsServiceDeRegisterCallback( DWORD /*Status*/, PVOID pQueryContext, PDNS_SERVICE_INSTANCE pInstance) { - ImplBase* impl = reinterpret_cast(pQueryContext); + HANDLE deregisterEvent = reinterpret_cast(pQueryContext); if (pInstance != nullptr) { DnsServiceFreeInstance(pInstance); - pInstance = nullptr; } - SetEvent(impl->event); + SetEvent(deregisterEvent); } void MulticastServiceAnnouncer::Stop() { @@ -188,9 +190,14 @@ void MulticastServiceAnnouncer::Stop() { return; } - pImpl->event = CreateEvent(NULL, true, false, NULL); + DnsServiceRegisterCancel(&pImpl->serviceCancel); + WaitForSingleObject(pImpl->registerEvent, INFINITE); + CloseHandle(pImpl->registerEvent); + pImpl->registerEvent = nullptr; + + HANDLE deregisterEvent = CreateEvent(NULL, true, false, NULL); DNS_SERVICE_REGISTER_REQUEST registerRequest = {}; - registerRequest.pQueryContext = static_cast(pImpl.get()); + registerRequest.pQueryContext = deregisterEvent; registerRequest.pRegisterCompletionCallback = DnsServiceDeRegisterCallback; registerRequest.Version = DNS_QUERY_REQUEST_VERSION1; registerRequest.unicastEnabled = false; @@ -198,11 +205,10 @@ void MulticastServiceAnnouncer::Stop() { registerRequest.InterfaceIndex = 0; if (DnsServiceDeRegister(®isterRequest, nullptr) == DNS_REQUEST_PENDING) { - WaitForSingleObject(pImpl->event, INFINITE); + WaitForSingleObject(deregisterEvent, INFINITE); } DnsServiceFreeInstance(pImpl->serviceInstance); pImpl->serviceInstance = nullptr; - CloseHandle(pImpl->event); - pImpl->event = nullptr; + CloseHandle(deregisterEvent); }