VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/darwin/HostDnsServiceDarwin.cpp@ 77872

Last change on this file since 77872 was 77872, checked in by vboxsync, 6 years ago

Main/HostDnsServiceDarwin: Fix hang during shutdown due to m_fStop variable not being set to true during shutdown and make sure the runloop is really stopped by using CFRunLoopStop() instead of CFRunLoopWakeUp(), also use atomics when accessing m_fStop and mark it as volatile

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.9 KB
Line 
1/* $Id: HostDnsServiceDarwin.cpp 77872 2019-03-25 17:16:23Z vboxsync $ */
2/** @file
3 * Darwin specific DNS information fetching.
4 */
5
6/*
7 * Copyright (C) 2004-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include <VBox/com/string.h>
19#include <VBox/com/ptr.h>
20
21
22#include <iprt/asm.h>
23#include <iprt/errcore.h>
24#include <iprt/thread.h>
25#include <iprt/semaphore.h>
26
27#include <CoreFoundation/CoreFoundation.h>
28#include <SystemConfiguration/SCDynamicStore.h>
29
30#include <string>
31#include <vector>
32#include "../HostDnsService.h"
33
34
35struct HostDnsServiceDarwin::Data
36{
37 Data()
38 : m_fStop(false) { }
39
40 SCDynamicStoreRef m_store;
41 CFRunLoopSourceRef m_DnsWatcher;
42 CFRunLoopRef m_RunLoopRef;
43 CFRunLoopSourceRef m_Stopper;
44 volatile bool m_fStop;
45 RTSEMEVENT m_evtStop;
46 static void performShutdownCallback(void *);
47};
48
49
50static const CFStringRef kStateNetworkGlobalDNSKey = CFSTR("State:/Network/Global/DNS");
51
52
53HostDnsServiceDarwin::HostDnsServiceDarwin():HostDnsMonitor(true),m(NULL)
54{
55 m = new HostDnsServiceDarwin::Data();
56}
57
58
59HostDnsServiceDarwin::~HostDnsServiceDarwin()
60{
61 if (!m)
62 return;
63
64 monitorThreadShutdown();
65
66 CFRelease(m->m_RunLoopRef);
67
68 CFRelease(m->m_DnsWatcher);
69
70 CFRelease(m->m_store);
71
72 RTSemEventDestroy(m->m_evtStop);
73
74 delete m;
75 m = NULL;
76}
77
78
79void HostDnsServiceDarwin::hostDnsServiceStoreCallback(void *, void *, void *info)
80{
81 HostDnsServiceDarwin *pThis = (HostDnsServiceDarwin *)info;
82
83 RTCLock grab(pThis->m_LockMtx);
84 pThis->updateInfo();
85}
86
87
88HRESULT HostDnsServiceDarwin::init(HostDnsMonitorProxy *proxy)
89{
90 SCDynamicStoreContext ctx;
91 RT_ZERO(ctx);
92
93 ctx.info = this;
94
95 m->m_store = SCDynamicStoreCreate(NULL, CFSTR("org.virtualbox.VBoxSVC"),
96 (SCDynamicStoreCallBack)HostDnsServiceDarwin::hostDnsServiceStoreCallback,
97 &ctx);
98 AssertReturn(m->m_store, E_FAIL);
99
100 m->m_DnsWatcher = SCDynamicStoreCreateRunLoopSource(NULL, m->m_store, 0);
101 if (!m->m_DnsWatcher)
102 return E_OUTOFMEMORY;
103
104 int rc = RTSemEventCreate(&m->m_evtStop);
105 AssertRCReturn(rc, E_FAIL);
106
107 CFRunLoopSourceContext sctx;
108 RT_ZERO(sctx);
109 sctx.perform = HostDnsServiceDarwin::Data::performShutdownCallback;
110 m->m_Stopper = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &sctx);
111 AssertReturn(m->m_Stopper, E_FAIL);
112
113 HRESULT hrc = HostDnsMonitor::init(proxy);
114 AssertComRCReturn(hrc, hrc);
115
116 return updateInfo();
117}
118
119
120void HostDnsServiceDarwin::monitorThreadShutdown()
121{
122 RTCLock grab(m_LockMtx);
123 if (!m->m_fStop)
124 {
125 ASMAtomicXchgBool(&m->m_fStop, true);
126 CFRunLoopSourceSignal(m->m_Stopper);
127 CFRunLoopStop(m->m_RunLoopRef);
128
129 RTSemEventWait(m->m_evtStop, RT_INDEFINITE_WAIT);
130 }
131}
132
133
134int HostDnsServiceDarwin::monitorWorker()
135{
136 m->m_RunLoopRef = CFRunLoopGetCurrent();
137 AssertReturn(m->m_RunLoopRef, VERR_INTERNAL_ERROR);
138
139 CFRetain(m->m_RunLoopRef);
140
141 CFArrayRef watchingArrayRef = CFArrayCreate(NULL,
142 (const void **)&kStateNetworkGlobalDNSKey,
143 1, &kCFTypeArrayCallBacks);
144 if (!watchingArrayRef)
145 {
146 CFRelease(m->m_DnsWatcher);
147 return E_OUTOFMEMORY;
148 }
149
150 if(SCDynamicStoreSetNotificationKeys(m->m_store, watchingArrayRef, NULL))
151 CFRunLoopAddSource(CFRunLoopGetCurrent(), m->m_DnsWatcher, kCFRunLoopCommonModes);
152
153 CFRelease(watchingArrayRef);
154
155 monitorThreadInitializationDone();
156
157 while (!ASMAtomicReadBool(&m->m_fStop))
158 {
159 CFRunLoopRun();
160 }
161
162 CFRelease(m->m_RunLoopRef);
163
164 /* We're notifying stopper thread. */
165 RTSemEventSignal(m->m_evtStop);
166
167 return VINF_SUCCESS;
168}
169
170
171HRESULT HostDnsServiceDarwin::updateInfo()
172{
173 CFPropertyListRef propertyRef = SCDynamicStoreCopyValue(m->m_store,
174 kStateNetworkGlobalDNSKey);
175 /**
176 * # scutil
177 * \> get State:/Network/Global/DNS
178 * \> d.show
179 * \<dictionary\> {
180 * DomainName : vvl-domain
181 * SearchDomains : \<array\> {
182 * 0 : vvl-domain
183 * 1 : de.vvl-domain.com
184 * }
185 * ServerAddresses : \<array\> {
186 * 0 : 192.168.1.4
187 * 1 : 192.168.1.1
188 * 2 : 8.8.4.4
189 * }
190 * }
191 */
192
193 if (!propertyRef)
194 return S_OK;
195
196 HostDnsInformation info;
197 CFStringRef domainNameRef = (CFStringRef)CFDictionaryGetValue(
198 static_cast<CFDictionaryRef>(propertyRef), CFSTR("DomainName"));
199 if (domainNameRef)
200 {
201 const char *pszDomainName = CFStringGetCStringPtr(domainNameRef,
202 CFStringGetSystemEncoding());
203 if (pszDomainName)
204 info.domain = pszDomainName;
205 }
206
207 int i, arrayCount;
208 CFArrayRef serverArrayRef = (CFArrayRef)CFDictionaryGetValue(
209 static_cast<CFDictionaryRef>(propertyRef), CFSTR("ServerAddresses"));
210 if (serverArrayRef)
211 {
212 arrayCount = CFArrayGetCount(serverArrayRef);
213 for (i = 0; i < arrayCount; ++i)
214 {
215 CFStringRef serverAddressRef = (CFStringRef)CFArrayGetValueAtIndex(serverArrayRef, i);
216 if (!serverArrayRef)
217 continue;
218
219 const char *pszServerAddress = CFStringGetCStringPtr(serverAddressRef,
220 CFStringGetSystemEncoding());
221 if (!pszServerAddress)
222 continue;
223
224 info.servers.push_back(std::string(pszServerAddress));
225 }
226 }
227
228 CFArrayRef searchArrayRef = (CFArrayRef)CFDictionaryGetValue(
229 static_cast<CFDictionaryRef>(propertyRef), CFSTR("SearchDomains"));
230 if (searchArrayRef)
231 {
232 arrayCount = CFArrayGetCount(searchArrayRef);
233
234 for (i = 0; i < arrayCount; ++i)
235 {
236 CFStringRef searchStringRef = (CFStringRef)CFArrayGetValueAtIndex(searchArrayRef, i);
237 if (!searchArrayRef)
238 continue;
239
240 const char *pszSearchString = CFStringGetCStringPtr(searchStringRef,
241 CFStringGetSystemEncoding());
242 if (!pszSearchString)
243 continue;
244
245 info.searchList.push_back(std::string(pszSearchString));
246 }
247 }
248
249 CFRelease(propertyRef);
250
251 setInfo(info);
252
253 return S_OK;
254}
255
256void HostDnsServiceDarwin::Data::performShutdownCallback(void *info)
257{
258 HostDnsServiceDarwin::Data *pThis = static_cast<HostDnsServiceDarwin::Data *>(info);
259 AssertPtrReturnVoid(pThis);
260 pThis->m_fStop = true;
261}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette