VirtualBox

Ignore:
Timestamp:
Jan 28, 2014 7:29:52 PM (11 years ago)
Author:
vboxsync
Message:

Main/HostDnsService:

  • Generic part could be used with threading on or off: OS which can monitor changes on DNS structures might need this (e.g. Windows, Darwin, Linux)
  • ResolvConf based (Linux, Solaris, FreeBSD ans Os/2) doesn't use scanf based resovl.conf parsing new Slirp's parser used instead. It's configured to provide strings instead of addresses. (to resolve xtracker/7034c2)
  • Darwin monitoring code has been refactored.
  • linux changed to handle cases described in xtracker/7034c3
  • Windows monitors changes on register changes.
File:
1 edited

Legend:

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

    r49460 r50263  
    3333#include <fcntl.h>
    3434
     35#include <linux/limits.h>
     36
    3537#include <sys/inotify.h>
    3638#include <sys/types.h>
     
    4244
    4345
    44 static RTTHREAD g_DnsMonitoringThread;
    45 static RTSEMEVENT g_DnsInitEvent;
    4646static int g_DnsMonitorStop[2];
     47
     48static const std::string g_EtcFolder = "/etc";
     49static const std::string g_ResolvConf = "resolv.conf";
     50static const std::string g_ResolvConfFullPath = "/etc/resolv.conf";
    4751
    4852class FileDescriptor
     
    7175        AssertReturnVoid(FileDescriptor::fd != -1);
    7276    }
    73 
    7477};
    7578
    76 
    77 class AutoWatcher:public FileDescriptor
    78 {
    79     public:
    80     AutoWatcher(const AutoNotify& notifier, const std::string& filename, uint32_t mask = IN_CLOSE_WRITE)
    81       :name(filename)
    82     {
    83         nfd = notifier.fileDescriptor();
    84         fd = inotify_add_watch(nfd, name.c_str(), mask);
    85         AssertMsgReturnVoid(fd != -1, ("failed to add watcher %s\n", name.c_str()));
    86 
    87         int opt = fcntl(fd, F_GETFL);
    88         opt |= O_NONBLOCK;
    89         fcntl(fd, F_SETFL, opt);
    90     }
    91 
    92     ~AutoWatcher()
    93     {
    94         int rc = inotify_rm_watch(nfd, fd);
    95         AssertMsgReturnVoid(rc != -1, ("Can't detach watcher %d from %d (%d: %s)\n", nfd, fd,
    96                                        errno, strerror(errno)));
    97     }
    98 
    99     private:
    100     std::string name;
    101     int nfd;
     79struct InotifyEventWithName
     80{
     81    struct inotify_event e;
     82    char name[NAME_MAX];
    10283};
    10384
    104 
    10585HostDnsServiceLinux::~HostDnsServiceLinux()
    10686{
    107     send(g_DnsMonitorStop[0], "", 1, 0);
     87    monitorThreadShutdown();
    10888}
    10989
    11090
    111 int HostDnsServiceLinux::hostMonitoringRoutine(RTTHREAD ThreadSelf, void *pvUser)
    112 {
    113     NOREF(ThreadSelf);
     91int HostDnsServiceLinux::monitorWorker()
     92{
     93
    11494    AutoNotify a;
    115     HostDnsServiceLinux *dns = static_cast<HostDnsServiceLinux *>(pvUser);
    116     AutoWatcher w(a, std::string(dns->resolvConf().c_str()));
    11795
    11896    int rc = socketpair(AF_LOCAL, SOCK_DGRAM, 0, g_DnsMonitorStop);
     
    131109    polls[1].events = POLLIN;
    132110
    133     RTSemEventSignal(g_DnsInitEvent);
    134 
     111    monitorThreadInitializationDone();
     112
     113    int wd[2];
     114    wd[0] = wd[1] = -1;
     115    /* inotify inialization */
     116    wd[0] = inotify_add_watch(a.fileDescriptor(),
     117                              g_ResolvConfFullPath.c_str(), IN_CLOSE_WRITE|IN_DELETE_SELF);
     118
     119    /**
     120     * If /etc/resolv.conf exists we want to listen for movements: because
     121     * # mv /etc/resolv.conf ...
     122     * won't arm IN_DELETE_SELF on wd[0] instead it will fire IN_MOVE_FROM on wd[1].
     123     *
     124     * Because on some distributions /etc/resolv.conf is link, wd[0] can't detect deletion,
     125     * it's recognizible on directory level (wd[1]) only.
     126     */
     127    wd[1] = inotify_add_watch(a.fileDescriptor(), g_EtcFolder.c_str(),
     128                              wd[0] == -1 ? IN_MOVED_TO|IN_CREATE : IN_MOVED_FROM|IN_DELETE);
     129
     130    struct InotifyEventWithName combo;
    135131    while(true)
    136132    {
     
    148144        if (polls[0].revents & POLLIN)
    149145        {
    150             dns->readResolvConf();
    151             /* notifyAll() takes required locks */
    152             dns->notifyAll();
    153 
    154             polls[0].revents = 0;
    155 
    156             inotify_event ev;
    157             rc = read(a.fileDescriptor(), static_cast<void *>(&ev), sizeof(ev));
    158             AssertMsg(rc == sizeof(ev) && ev.wd == w.fileDescriptor(), ("Hmm, debug me"));
     146            RT_ZERO(combo);
     147            ssize_t r = read(polls[0].fd, static_cast<void *>(&combo), sizeof(combo));
     148
     149            if (combo.e.wd == wd[0])
     150            {
     151                if (combo.e.mask & IN_CLOSE_WRITE)
     152                {
     153                    readResolvConf();
     154                    /* notifyAll() takes required locks */
     155                    notifyAll();
     156                }
     157                else if (combo.e.mask & IN_DELETE_SELF)
     158                {
     159                    inotify_rm_watch(a.fileDescriptor(), wd[0]); /* removes file watcher */
     160                    inotify_add_watch(a.fileDescriptor(), g_EtcFolder.c_str(),
     161                                      IN_MOVED_TO|IN_CREATE); /* alter folder watcher */
     162                }
     163                else if (combo.e.mask & IN_IGNORED)
     164                {
     165                    wd[0] = -1; /* we want receive any events on this watch */
     166                }
     167                else
     168                {
     169                    /**
     170                     * It shouldn't happen, in release we will just ignore in debug
     171                     * we will have to chance to look at into inotify_event
     172                     */
     173                    AssertMsgFailed(("Debug Me!!!"));
     174                }
     175            }
     176            else if (combo.e.wd == wd[1])
     177            {
     178                if (   combo.e.mask & IN_MOVED_FROM
     179                    || combo.e.mask & IN_DELETE)
     180                {
     181                    if (g_ResolvConf == combo.e.name)
     182                    {
     183                        /**
     184                         * Our file has been moved so we should change watching mode.
     185                         */
     186                        inotify_rm_watch(a.fileDescriptor(), wd[0]);
     187                        wd[1] = inotify_add_watch(a.fileDescriptor(), g_EtcFolder.c_str(),
     188                                                  IN_MOVED_TO|IN_CREATE);
     189                        AssertMsg(wd[1] != -1,
     190                                  ("It shouldn't happen, further investigation is needed\n"));
     191                    }
     192                }
     193                else
     194                {
     195                    AssertMsg(combo.e.mask & (IN_MOVED_TO|IN_CREATE),
     196                              ("%RX32 event isn't expected, we are waiting for IN_MOVED|IN_CREATE\n",
     197                               combo.e.mask));
     198                    if (g_ResolvConf == combo.e.name)
     199                    {
     200                        AssertMsg(wd[0] == -1, ("We haven't removed file watcher first\n"));
     201
     202                        /* alter folder watcher*/
     203                        wd[1] = inotify_add_watch(a.fileDescriptor(), g_EtcFolder.c_str(),
     204                                                  IN_MOVED_FROM|IN_DELETE);
     205                        AssertMsg(wd[1] != -1, ("It shouldn't happen.\n"));
     206
     207                        wd[0] = inotify_add_watch(a.fileDescriptor(),
     208                                                  g_ResolvConfFullPath.c_str(),
     209                                                  IN_CLOSE_WRITE | IN_DELETE_SELF);
     210                        AssertMsg(wd[0] != -1, ("Adding watcher to file (%s) has been failed!\n",
     211                                                g_ResolvConfFullPath.c_str()));
     212
     213                        /* Notify our listeners */
     214                        readResolvConf();
     215                        notifyAll();
     216
     217                    }
     218                }
     219            }
     220            else
     221            {
     222                /* It shouldn't happen */
     223                AssertMsgFailed(("Shouldn't happen! Please debug me!"));
     224            }
    159225        }
    160226    }
     
    162228
    163229
    164 HRESULT HostDnsServiceLinux::init(const char *aResolvConfFileName)
    165 {
    166     HRESULT hrc = HostDnsServiceResolvConf::init(aResolvConfFileName);
    167     AssertComRCReturnRC(hrc);
    168 
    169     int rc = RTSemEventCreate(&g_DnsInitEvent);
    170     AssertRCReturn(rc, E_FAIL);
    171 
    172     rc = RTThreadCreate(&g_DnsMonitoringThread, HostDnsServiceLinux::hostMonitoringRoutine,
    173                         this, 128 * _1K, RTTHREADTYPE_IO, 0, "dns-monitor");
    174     AssertRCReturn(rc, E_FAIL);
    175 
    176     RTSemEventWait(g_DnsInitEvent, RT_INDEFINITE_WAIT);
    177 
    178     return S_OK;
     230void HostDnsServiceLinux::monitorThreadShutdown()
     231{
     232    send(g_DnsMonitorStop[0], "", 1, 0);
    179233}
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