VirtualBox

Changeset 98071 in vbox for trunk/src/VBox/Main/src-server


Ignore:
Timestamp:
Jan 13, 2023 10:38:26 AM (2 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
155196
Message:

Main/HostDnsServiceLinux.cpp: Massaged the resolv.conf monitoring code a bit more. bugref:10255

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

Legend:

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

    r96407 r98071  
    249249public:
    250250
    251     HostDnsServiceLinux() : HostDnsServiceResolvConf(true) {}
     251    HostDnsServiceLinux() : HostDnsServiceResolvConf(true), m_fdShutdown(-1) {}
    252252    virtual ~HostDnsServiceLinux();
    253253
     
    260260    int monitorThreadShutdown(RTMSINTERVAL uTimeoutMs);
    261261    int monitorThreadProc(void);
     262
     263    /** Socket end to write shutdown notification to, so the monitor thread will
     264     *  wake up and terminate. */
     265    int m_fdShutdown;
    262266};
    263267
  • trunk/src/VBox/Main/src-server/linux/HostDnsServiceLinux.cpp

    r98068 r98071  
    6666*   Global Variables                                                                                                             *
    6767*********************************************************************************************************************************/
    68 static int g_DnsMonitorStop[2];
    69 
    7068static const char g_szEtcFolder[]          = "/etc";
    7169static const char g_szResolvConfPath[]     = "/etc/resolv.conf";
     
    7371
    7472
    75 class FileDescriptor
    76 {
    77 public:
    78     FileDescriptor(int d = -1)
    79         : fd(d)
    80     {}
    81 
    82     virtual ~FileDescriptor() {
    83         if (fd != -1)
    84             close(fd);
     73HostDnsServiceLinux::~HostDnsServiceLinux()
     74{
     75    if (m_fdShutdown >= 0)
     76    {
     77        close(m_fdShutdown);
     78        m_fdShutdown = -1;
    8579    }
    86 
    87     int fileDescriptor() const {return fd;}
    88 
    89 protected:
    90     int fd;
    91 };
    92 
    93 
    94 class AutoNotify : public FileDescriptor
    95 {
    96 public:
    97     AutoNotify()
    98     {
    99         FileDescriptor::fd = inotify_init();
    100         AssertReturnVoid(FileDescriptor::fd != -1);
    101     }
    102 };
    103 
    104 HostDnsServiceLinux::~HostDnsServiceLinux()
    105 {
    10680}
    10781
     
    11589    RT_NOREF(uTimeoutMs);
    11690
    117     send(g_DnsMonitorStop[0], "", 1, 0);
    118 
    119     /** @todo r=andy Do we have to wait for something here? Can this fail? */
     91    if (m_fdShutdown >= 0)
     92        send(m_fdShutdown, "", 1, MSG_NOSIGNAL);
     93
    12094    return VINF_SUCCESS;
    12195}
    12296
    123 #ifdef LOG_ENABLED
    12497/**
    12598 * Format the notifcation event mask into a buffer for logging purposes.
     
    170143    return psz;
    171144}
    172 #endif
    173 
    174145
    175146/**
     
    204175}
    205176
     177/** @todo If this code is needed elsewhere, we should abstract it into an IPRT
     178 *        thingy that monitors a file (path) for changes.  This code is a little
     179 *        bit too complex to be duplicated. */
    206180int HostDnsServiceLinux::monitorThreadProc(void)
    207181{
    208182    /*
    209      * inotify initialization.
    210      *
    211      * The order here helps keep the descriptor values stable.
     183     * Create a socket pair for signalling shutdown (see monitorThreadShutdown).
     184     * ASSUME Linux 2.6.27 or later and that we can use SOCK_CLOEXEC.
     185     */
     186    int aiStopPair[2];
     187    int rc = socketpair(AF_LOCAL, SOCK_DGRAM | SOCK_CLOEXEC, 0, aiStopPair);
     188    int iErr = errno;
     189    AssertLogRelMsgReturn(rc == 0, ("socketpair: failed (%d: %s)\n", iErr, strerror(iErr)), RTErrConvertFromErrno(iErr));
     190
     191    m_fdShutdown = aiStopPair[0];
     192
     193    onMonitorThreadInitDone();
     194
     195    /*
     196     * inotify initialization (using inotify_init1 w/ IN_CLOEXEC introduced
     197     * in 2.6.27 shouldn't be a problem any more).
    212198     *
    213199     * Note! Ignoring failures here is safe, because poll will ignore entires
    214200     *       with negative fd values.
    215201     */
    216     AutoNotify Notify;
    217 
    218     /* Monitor the /etc directory so we can detect moves, unliking and creations
     202    int const iNotifyFd = inotify_init1(IN_CLOEXEC);
     203    if (iNotifyFd < 0)
     204        LogRel(("HostDnsServiceLinux::monitorThreadProc: Warning! inotify_init failed (errno=%d)\n", errno));
     205
     206    /* Monitor the /etc directory so we can detect moves, creating and unlinking
    219207       involving /etc/resolv.conf:  */
    220     int const iWdDir = inotify_add_watch(Notify.fileDescriptor(), g_szEtcFolder, IN_MOVE | IN_CREATE | IN_DELETE);
     208    int const iWdDir = inotify_add_watch(iNotifyFd, g_szEtcFolder, IN_MOVE | IN_CREATE | IN_DELETE);
    221209
    222210    /* In case g_szResolvConfPath is a symbolic link, monitor the target directory
    223        too for changes to what it links to. */
     211       too for changes to what it links to (kept up to date via iWdDir). */
    224212    char   szRealResolvConf[PATH_MAX];
    225213    size_t offRealResolvConfName = 0;
    226     int iWdSymDir = ::monitorSymlinkedDir(Notify.fileDescriptor(), szRealResolvConf, &offRealResolvConfName);
     214    int iWdSymDir = ::monitorSymlinkedDir(iNotifyFd, szRealResolvConf, &offRealResolvConfName);
    227215
    228216    /* Monitor the resolv.conf itself if it exists, following all symlinks. */
    229     int iWdFile = inotify_add_watch(Notify.fileDescriptor(), g_szResolvConfPath, IN_CLOSE_WRITE | IN_DELETE_SELF);
    230 
    231     Log5Func(("iWdDir=%d iWdSymDir=%d iWdFile=%d\n", iWdDir, iWdSymDir, iWdFile));
    232 
    233     /*
    234      * Create a socket pair for signalling shutdown via (see monitorThreadShutdown).
    235      */
    236     int rc = socketpair(AF_LOCAL, SOCK_DGRAM, 0, g_DnsMonitorStop);
    237     AssertMsgReturn(rc == 0, ("socketpair: failed (%d: %s)\n", errno, strerror(errno)), E_FAIL);
    238 
    239     /* automatic cleanup tricks */
    240     FileDescriptor stopper0(g_DnsMonitorStop[0]);
    241     FileDescriptor stopper1(g_DnsMonitorStop[1]);
     217    int iWdFile = inotify_add_watch(iNotifyFd, g_szResolvConfPath, IN_CLOSE_WRITE | IN_DELETE_SELF);
     218
     219    LogRel5(("HostDnsServiceLinux::monitorThreadProc: inotify: %d - iWdDir=%d iWdSymDir=%d iWdFile=%d\n",
     220             iNotifyFd, iWdDir, iWdSymDir, iWdFile));
    242221
    243222    /*
     
    247226    RT_ZERO(aFdPolls);
    248227
    249     aFdPolls[0].fd = Notify.fileDescriptor();
     228    aFdPolls[0].fd = iNotifyFd;
    250229    aFdPolls[0].events = POLLIN;
    251230
    252     aFdPolls[1].fd = g_DnsMonitorStop[1];
     231    aFdPolls[1].fd = aiStopPair[1];
    253232    aFdPolls[1].events = POLLIN;
    254 
    255     onMonitorThreadInitDone();
    256233
    257234    /*
    258235     * The monitoring loop.
    259236     */
     237    int vrcRet = VINF_SUCCESS;
    260238    for (;;)
    261239    {
     
    266244        if (rc == -1)
    267245        {
    268             LogRelMax(32, ("HostDnsServiceLinux::monitorThreadProc: poll failed %d: errno=%d\n", rc, errno));
    269             RTThreadSleep(1);
     246            if (errno != EINTR)
     247            {
     248                LogRelMax(32, ("HostDnsServiceLinux::monitorThreadProc: poll failed %d: errno=%d\n", rc, errno));
     249                RTThreadSleep(1);
     250            }
    270251            continue;
    271252        }
    272253        Log5Func(("poll returns %d: [0]=%#x [1]=%#x\n", rc, aFdPolls[1].revents, aFdPolls[0].revents));
    273254
    274         AssertMsgReturn(   (aFdPolls[0].revents & (POLLERR | POLLNVAL)) == 0
    275                         && (aFdPolls[1].revents & (POLLERR | POLLNVAL)) == 0, ("Debug Me"), VERR_INTERNAL_ERROR);
    276 
     255        AssertMsgBreakStmt(   (aFdPolls[0].revents & (POLLERR | POLLNVAL)) == 0 /* (ok for fd=-1 too, revents=0 then) */
     256                           && (aFdPolls[1].revents & (POLLERR | POLLNVAL)) == 0,
     257                              ("Debug Me: [0]=%d,%#x [1]=%d, %#x\n",
     258                               aFdPolls[0].fd, aFdPolls[0].revents, aFdPolls[0].fd, aFdPolls[1].revents),
     259                           vrcRet = VERR_INTERNAL_ERROR);
    277260
    278261        /*
     
    280263         */
    281264        if (aFdPolls[1].revents & POLLIN)
    282             return VINF_SUCCESS;
     265            break; /** @todo should probably drain aiStopPair[1] here if we're really paranoid.
     266                    * we'll be closing our end of the socket/pipe, so any stuck write
     267                    * should return too (ECONNRESET, ENOTCONN or EPIPE). */
    283268
    284269        if (aFdPolls[0].revents & POLLIN)
     
    294279            } uEvtBuf;
    295280
    296             ssize_t cbEvents = read(Notify.fileDescriptor(), &uEvtBuf, sizeof(uEvtBuf));
     281            ssize_t cbEvents = read(iNotifyFd, &uEvtBuf, sizeof(uEvtBuf));
    297282            Log5Func(("read(inotify) -> %zd\n", cbEvents));
    298283            if (cbEvents > 0)
     
    313298            while (cbEvents >= (ssize_t)INOTIFY_EVENT_SIZE)
    314299            {
    315 #ifdef LOG_ENABLED
    316300                char szTmp[64];
    317301                if (pCurEvt->len == 0)
    318                     Log5Func(("event: wd=%#x mask=%#x (%s) cookie=%#x\n", pCurEvt->wd, pCurEvt->mask,
    319                               InotifyMaskToStr(szTmp, sizeof(szTmp), pCurEvt->mask), pCurEvt->cookie));
     302                    LogRel5(("HostDnsServiceLinux::monitorThreadProc: event: wd=%#x mask=%#x (%s) cookie=%#x\n",
     303                             pCurEvt->wd, pCurEvt->mask, InotifyMaskToStr(szTmp, sizeof(szTmp), pCurEvt->mask), pCurEvt->cookie));
    320304                else
    321                     Log5Func(("event: wd=%#x mask=%#x (%s) cookie=%#x len=%#x '%s'\n",
     305                    LogRel5(("HostDnsServiceLinux::monitorThreadProc: event: wd=%#x mask=%#x (%s) cookie=%#x len=%#x '%s'\n",
    322306                              pCurEvt->wd, pCurEvt->mask, InotifyMaskToStr(szTmp, sizeof(szTmp), pCurEvt->mask),
    323307                              pCurEvt->cookie, pCurEvt->len, pCurEvt->name));
    324 #endif
    325308
    326309                /*
     
    339322                        if (iWdFileNew != -1)
    340323                        {
    341                             rc = inotify_rm_watch(Notify.fileDescriptor(), iWdFileNew);
     324                            rc = inotify_rm_watch(iNotifyFd, iWdFileNew);
    342325                            AssertMsg(rc >= 0, ("%d/%d\n", rc, errno));
    343326                            iWdFileNew = -1;
     
    367350                            if (iWdFileNew >= 0)
    368351                            {
    369                                 rc = inotify_rm_watch(Notify.fileDescriptor(), iWdFileNew);
     352                                rc = inotify_rm_watch(iNotifyFd, iWdFileNew);
    370353                                Log5Func(("dir: moved / created / deleted: dropped file watch (%d - rc=%d/err=%d)\n",
    371354                                          iWdFileNew, rc, errno));
     
    374357                            if (iWdSymDirNew >= 0)
    375358                            {
    376                                 rc = inotify_rm_watch(Notify.fileDescriptor(), iWdSymDirNew);
     359                                rc = inotify_rm_watch(iNotifyFd, iWdSymDirNew);
    377360                                Log5Func(("dir: moved / created / deleted: dropped symlinked dir watch (%d - %s/%s - rc=%d/err=%d)\n",
    378361                                          iWdSymDirNew, szRealResolvConf, &szRealResolvConf[offRealResolvConfName], rc, errno));
     
    385368                                fTryReRead = true;
    386369
    387                                 iWdSymDirNew = ::monitorSymlinkedDir(Notify.fileDescriptor(),
    388                                                                      szRealResolvConf, &offRealResolvConfName);
     370                                iWdSymDirNew = ::monitorSymlinkedDir(iNotifyFd, szRealResolvConf, &offRealResolvConfName);
    389371                                if (iWdSymDirNew < 0)
    390372                                    Log5Func(("dir: moved_to / created: re-stablished symlinked-directory monitoring: iWdSymDir=%d (%s/%s)\n",
     
    415397                        if (iWdFileNew >= 0)
    416398                        {
    417                             rc = inotify_rm_watch(Notify.fileDescriptor(), iWdFileNew);
     399                            rc = inotify_rm_watch(iNotifyFd, iWdFileNew);
    418400                            Log5Func(("symdir: moved / created / deleted: drop file watch (%d - rc=%d/err=%d)\n",
    419401                                      iWdFileNew, rc, errno));
     
    452434            if (iWdFile == -1)
    453435            {
    454                 iWdFile = inotify_add_watch(Notify.fileDescriptor(), g_szResolvConfPath, IN_CLOSE_WRITE | IN_DELETE_SELF);
     436                iWdFile = inotify_add_watch(iNotifyFd, g_szResolvConfPath, IN_CLOSE_WRITE | IN_DELETE_SELF);
    455437                if (iWdFile >= 0)
    456438                {
     
    467449            {
    468450                Log5Func(("Calling readResolvConf()...\n"));
    469                 readResolvConf();
     451                try
     452                {
     453                    readResolvConf();
     454                }
     455                catch (...)
     456                {
     457                    LogRel(("HostDnsServiceLinux::monitorThreadProc: readResolvConf threw exception!\n"));
     458                }
    470459            }
    471460        }
    472461    }
    473 }
    474 
     462
     463    /*
     464     * Close file descriptors.
     465     */
     466    if (aiStopPair[0] == m_fdShutdown) /* paranoia */
     467    {
     468        m_fdShutdown = -1;
     469        close(aiStopPair[0]);
     470    }
     471    close(aiStopPair[1]);
     472    close(iNotifyFd);
     473    return vrcRet;
     474}
     475
Note: See TracChangeset for help on using the changeset viewer.

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