VirtualBox

Changeset 108010 in vbox for trunk/src/VBox/Main


Ignore:
Timestamp:
Jan 31, 2025 11:49:41 PM (3 weeks ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
167282
Message:

Main/HostDnsService.cpp: Fixed lock order problem with HostDnsMonitorProxy::updateInfo / HostDnsMonitorProxy::pollGlobalExtraData / VirtualBox::getExtraData after r166866. This replaces the IPRT scope-based locking with the main-style locking for flexibility.

Location:
trunk/src/VBox/Main/src-server
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-server/HostDnsService.cpp

    r106061 r108010  
    9595}
    9696
    97 DECLINLINE(void) detachVectorOfString(const std::vector<std::string>& v, std::vector<com::Utf8Str> &aArray)
     97DECLINLINE(void) detachVectorOfStrings(const std::vector<std::string>& v, std::vector<com::Utf8Str> &aArray)
    9898{
    9999    aArray.resize(v.size());
     
    247247}
    248248
    249 void HostDnsMonitorProxy::pollGlobalExtraData(void)
    250 {
     249/**
     250 * Updates HostDnsMonitorProxy::Data::fLaxComparison every 30 seconds, returning
     251 * the new value.
     252 *
     253 * @note This will leave the lock while calling IVirtualBox::GetExtraData.
     254 */
     255uint32_t HostDnsMonitorProxy::pollGlobalExtraData(AutoWriteLock &aLock)
     256{
     257    uint32_t    fLaxComparison = m->fLaxComparison;
    251258    VirtualBox *pVirtualBox = m->pVirtualBox;
    252     if (RT_UNLIKELY(pVirtualBox == NULL))
    253         return;
    254 
    255     uint64_t uNow = RTTimeNanoTS();
    256     if (uNow - m->uLastExtraDataPoll >= RT_NS_30SEC || m->uLastExtraDataPoll == 0)
    257     {
    258         m->uLastExtraDataPoll = uNow;
    259 
    260         /*
    261          * Should we ignore the order of DNS servers?
    262          */
    263         const com::Bstr bstrHostDNSOrderIgnoreKey("VBoxInternal2/HostDNSOrderIgnore");
    264         com::Bstr bstrHostDNSOrderIgnore;
    265         pVirtualBox->GetExtraData(bstrHostDNSOrderIgnoreKey.raw(),
    266                                  bstrHostDNSOrderIgnore.asOutParam());
    267         uint32_t fDNSOrderIgnore = 0;
    268         if (bstrHostDNSOrderIgnore.isNotEmpty())
     259    if (pVirtualBox)
     260    {
     261        uint64_t uNow = RTTimeNanoTS();
     262        if (uNow - m->uLastExtraDataPoll >= RT_NS_30SEC || m->uLastExtraDataPoll == 0)
    269263        {
    270             if (bstrHostDNSOrderIgnore != "0")
     264            m->uLastExtraDataPoll = uNow;
     265
     266            /* We cannot do GetExtraData holding this lock, so temporarily release it. */
     267            aLock.release();
     268
     269            /*
     270             * Should we ignore the order of DNS servers?
     271             */
     272            const com::Bstr bstrHostDNSOrderIgnoreKey("VBoxInternal2/HostDNSOrderIgnore");
     273            com::Bstr bstrHostDNSOrderIgnore;
     274            pVirtualBox->GetExtraData(bstrHostDNSOrderIgnoreKey.raw(), bstrHostDNSOrderIgnore.asOutParam());
     275            uint32_t fDNSOrderIgnore = 0;
     276            if (bstrHostDNSOrderIgnore.isNotEmpty() && bstrHostDNSOrderIgnore != "0")
    271277                fDNSOrderIgnore = HostDnsInformation::IGNORE_SERVER_ORDER;
     278
     279            if (fDNSOrderIgnore != (fLaxComparison & HostDnsInformation::IGNORE_SERVER_ORDER))
     280            {
     281                fLaxComparison ^= HostDnsInformation::IGNORE_SERVER_ORDER;
     282                LogRel(("HostDnsMonitor: %ls=%ls\n", bstrHostDNSOrderIgnoreKey.raw(), bstrHostDNSOrderIgnore.raw()));
     283            }
     284
     285            /*
     286             * Should we ignore changes to the domain name or the search list?
     287             */
     288            const com::Bstr bstrHostDNSSuffixesIgnoreKey("VBoxInternal2/HostDNSSuffixesIgnore");
     289            com::Bstr bstrHostDNSSuffixesIgnore;
     290            pVirtualBox->GetExtraData(bstrHostDNSSuffixesIgnoreKey.raw(), bstrHostDNSSuffixesIgnore.asOutParam());
     291            uint32_t fDNSSuffixesIgnore = 0;
     292            if (bstrHostDNSSuffixesIgnore.isNotEmpty() && bstrHostDNSSuffixesIgnore != "0")
     293                fDNSSuffixesIgnore = HostDnsInformation::IGNORE_SUFFIXES;
     294
     295            if (fDNSSuffixesIgnore != (fLaxComparison & HostDnsInformation::IGNORE_SUFFIXES))
     296            {
     297                fLaxComparison ^= HostDnsInformation::IGNORE_SUFFIXES;
     298                LogRel(("HostDnsMonitor: %ls=%ls\n", bstrHostDNSSuffixesIgnoreKey.raw(), bstrHostDNSSuffixesIgnore.raw()));
     299            }
     300
     301            aLock.acquire();
     302            m->fLaxComparison = fLaxComparison;
    272303        }
    273 
    274         if (fDNSOrderIgnore != (m->fLaxComparison & HostDnsInformation::IGNORE_SERVER_ORDER))
    275         {
    276 
    277             m->fLaxComparison ^= HostDnsInformation::IGNORE_SERVER_ORDER;
    278             LogRel(("HostDnsMonitor: %ls=%ls\n",
    279                     bstrHostDNSOrderIgnoreKey.raw(),
    280                     bstrHostDNSOrderIgnore.raw()));
    281         }
    282 
    283         /*
    284          * Should we ignore changes to the domain name or the search list?
    285          */
    286         const com::Bstr bstrHostDNSSuffixesIgnoreKey("VBoxInternal2/HostDNSSuffixesIgnore");
    287         com::Bstr bstrHostDNSSuffixesIgnore;
    288         pVirtualBox->GetExtraData(bstrHostDNSSuffixesIgnoreKey.raw(),
    289                                  bstrHostDNSSuffixesIgnore.asOutParam());
    290         uint32_t fDNSSuffixesIgnore = 0;
    291         if (bstrHostDNSSuffixesIgnore.isNotEmpty())
    292         {
    293             if (bstrHostDNSSuffixesIgnore != "0")
    294                 fDNSSuffixesIgnore = HostDnsInformation::IGNORE_SUFFIXES;
    295         }
    296 
    297         if (fDNSSuffixesIgnore != (m->fLaxComparison & HostDnsInformation::IGNORE_SUFFIXES))
    298         {
    299 
    300             m->fLaxComparison ^= HostDnsInformation::IGNORE_SUFFIXES;
    301             LogRel(("HostDnsMonitor: %ls=%ls\n",
    302                     bstrHostDNSSuffixesIgnoreKey.raw(),
    303                     bstrHostDNSSuffixesIgnore.raw()));
    304         }
    305     }
     304    }
     305    return fLaxComparison;
    306306}
    307307
     
    324324HostDnsMonitorProxy::HostDnsMonitorProxy()
    325325    : m(NULL)
     326    , m_ObjectLock(LOCKCLASS_OTHEROBJECT, "HostDnsMonitorProxy")
    326327{
    327328}
     
    332333}
    333334
    334 HRESULT HostDnsMonitorProxy::init(VirtualBox* aParent)
     335HRESULT HostDnsMonitorProxy::init(VirtualBox *aParent)
    335336{
    336337    AssertMsgReturn(m == NULL, ("DNS monitor proxy already initialized\n"), E_FAIL);
     
    363364}
    364365
     366util::LockHandle *HostDnsMonitorProxy::lockHandle() const
     367{
     368    return &m_ObjectLock;
     369}
     370
    365371void HostDnsMonitorProxy::notify(const HostDnsInformation &info)
    366372{
     
    372378HRESULT HostDnsMonitorProxy::GetNameServers(std::vector<com::Utf8Str> &aNameServers)
    373379{
     380    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    374381    AssertReturn(m != NULL, E_FAIL);
    375     RTCLock grab(m_LockMtx);
    376382
    377383    LogRel(("HostDnsMonitorProxy::GetNameServers:\n"));
    378384    dumpHostDnsStrVector("name server", m->info.servers);
    379385
    380     detachVectorOfString(m->info.servers, aNameServers);
     386    detachVectorOfStrings(m->info.servers, aNameServers);
    381387
    382388    return S_OK;
     
    385391HRESULT HostDnsMonitorProxy::GetDomainName(com::Utf8Str *pDomainName)
    386392{
     393    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    387394    AssertReturn(m != NULL, E_FAIL);
    388     RTCLock grab(m_LockMtx);
    389 
    390     LogRel(("HostDnsMonitorProxy::GetDomainName: %s\n",
    391             m->info.domain.empty() ? "no domain set" : m->info.domain.c_str()));
    392 
     395
     396    LogRel(("HostDnsMonitorProxy::GetDomainName: %s\n", m->info.domain.empty() ? "no domain set" : m->info.domain.c_str()));
    393397    *pDomainName = m->info.domain.c_str();
    394398
     
    398402HRESULT HostDnsMonitorProxy::GetSearchStrings(std::vector<com::Utf8Str> &aSearchStrings)
    399403{
     404    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    400405    AssertReturn(m != NULL, E_FAIL);
    401     RTCLock grab(m_LockMtx);
    402406
    403407    LogRel(("HostDnsMonitorProxy::GetSearchStrings:\n"));
    404408    dumpHostDnsStrVector("search string", m->info.searchList);
    405409
    406     detachVectorOfString(m->info.searchList, aSearchStrings);
     410    detachVectorOfStrings(m->info.searchList, aSearchStrings);
    407411
    408412    return S_OK;
     
    411415bool HostDnsMonitorProxy::updateInfo(const HostDnsInformation &info)
    412416{
     417    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    413418    LogRel(("HostDnsMonitor: updating information\n"));
    414     RTCLock grab(m_LockMtx);
    415419
    416420    if (info.equals(m->info))
     
    420424    }
    421425
    422     pollGlobalExtraData();
     426    uint32_t const fLaxComparison = pollGlobalExtraData(alock);
    423427
    424428    LogRel(("HostDnsMonitor: old information\n"));
     
    427431    dumpHostDnsInformation(info);
    428432
    429     bool fIgnore = m->fLaxComparison != 0 && info.equals(m->info, m->fLaxComparison);
     433    bool fIgnore = fLaxComparison != 0 && info.equals(m->info, fLaxComparison);
    430434    m->info = info;
    431435
  • trunk/src/VBox/Main/src-server/HostDnsService.h

    r106061 r108010  
    6262/**
    6363 * Base class for host DNS service implementations.
     64 *
    6465 * This class supposed to be a real DNS monitor object as a singleton,
    6566 * so it lifecycle starts and ends together with VBoxSVC.
     
    118119 */
    119120class HostDnsMonitorProxy
     121    : public Lockable
    120122{
    121123public:
     
    134136    HRESULT GetSearchStrings(std::vector<com::Utf8Str> &aSearchStrings);
    135137
    136 private:
    137 
    138     void pollGlobalExtraData(void);
     138    LockHandle *lockHandle() const RT_OVERRIDE;
     139
     140private:
     141
     142    uint32_t pollGlobalExtraData(AutoWriteLock &aLock);
    139143    bool updateInfo(const HostDnsInformation &info);
    140144
    141145private:
    142 
    143     mutable RTCLockMtx m_LockMtx;
    144 
    145     struct Data;
    146     Data *m;
     146    struct Data;
     147    Data *m;
     148    /** Object lock object. */
     149    mutable util::RWLockHandle m_ObjectLock;
    147150};
    148151
     
    162165protected:
    163166
    164     int monitorThreadShutdown(RTMSINTERVAL uTimeoutMs);
    165     int monitorThreadProc(void);
     167    int monitorThreadShutdown(RTMSINTERVAL uTimeoutMs) RT_OVERRIDE;
     168    int monitorThreadProc(void) RT_OVERRIDE;
    166169
    167170private:
     
    187190protected:
    188191
    189     int monitorThreadShutdown(RTMSINTERVAL uTimeoutMs);
    190     int monitorThreadProc(void);
     192    int monitorThreadShutdown(RTMSINTERVAL uTimeoutMs) RT_OVERRIDE;
     193    int monitorThreadProc(void) RT_OVERRIDE;
    191194
    192195private:
     
    238241public:
    239242
    240     virtual HRESULT init(HostDnsMonitorProxy *pProxy) {
     243    virtual HRESULT init(HostDnsMonitorProxy *pProxy)
     244    {
    241245        return HostDnsServiceResolvConf::init(pProxy, "/etc/resolv.conf");
    242246    }
     
    258262protected:
    259263
    260     int monitorThreadShutdown(RTMSINTERVAL uTimeoutMs);
    261     int monitorThreadProc(void);
     264    int monitorThreadShutdown(RTMSINTERVAL uTimeoutMs) RT_OVERRIDE;
     265    int monitorThreadProc(void) RT_OVERRIDE;
    262266
    263267    /** Socket end to write shutdown notification to, so the monitor thread will
  • trunk/src/VBox/Main/src-server/darwin/HostDnsServiceDarwin.cpp

    r107621 r108010  
    115115
    116116    CFRelease(m->m_SourceStop);
     117    m->m_SourceStop = NULL;
    117118    CFRelease(m->m_RunLoopRef);
     119    m->m_RunLoopRef = NULL;
    118120    CFRelease(m->m_DnsWatcher);
     121    m->m_DnsWatcher = NULL;
    119122    CFRelease(m->m_store);
     123    m->m_store = NULL;
    120124
    121125    RTSemEventDestroy(m->m_evtStop);
     126    m->m_evtStop = NIL_RTSEMEVENT;
    122127}
    123128
     
    131136        CFRunLoopStop(m->m_RunLoopRef);
    132137
     138        grab.release(); /* bird 2025-01-31: May deadlock otherwise since hostDnsServiceStoreCallback takes the lock. */
    133139        RTSemEventWait(m->m_evtStop, uTimeoutMs);
    134140    }
     
    163169
    164170    /* Trigger initial update. */
    165     int vrc = updateInfo();
     171    int vrc = updateInfo(); /** @todo r=bird: Not holding the lock here, unlike what hostDnsServiceStoreCallback does... */
    166172    AssertRC(vrc); /* Not fatal in release builds. */  /** @todo r=bird: The function always returns VINF_SUCCESS. */
    167173
Note: See TracChangeset for help on using the changeset viewer.

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