1 | /* $Id: HostDnsServiceLinux.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
|
---|
2 | /** @file
|
---|
3 | * Linux specific DNS information fetching.
|
---|
4 | */
|
---|
5 |
|
---|
6 | /*
|
---|
7 | * Copyright (C) 2013-2024 Oracle and/or its affiliates.
|
---|
8 | *
|
---|
9 | * This file is part of VirtualBox base platform packages, as
|
---|
10 | * available from https://www.virtualbox.org.
|
---|
11 | *
|
---|
12 | * This program is free software; you can redistribute it and/or
|
---|
13 | * modify it under the terms of the GNU General Public License
|
---|
14 | * as published by the Free Software Foundation, in version 3 of the
|
---|
15 | * License.
|
---|
16 | *
|
---|
17 | * This program is distributed in the hope that it will be useful, but
|
---|
18 | * WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
20 | * General Public License for more details.
|
---|
21 | *
|
---|
22 | * You should have received a copy of the GNU General Public License
|
---|
23 | * along with this program; if not, see <https://www.gnu.org/licenses>.
|
---|
24 | *
|
---|
25 | * SPDX-License-Identifier: GPL-3.0-only
|
---|
26 | */
|
---|
27 |
|
---|
28 |
|
---|
29 | /*********************************************************************************************************************************
|
---|
30 | * Header Files *
|
---|
31 | *********************************************************************************************************************************/
|
---|
32 | #define LOG_GROUP LOG_GROUP_MAIN_HOST
|
---|
33 | #include <iprt/assert.h>
|
---|
34 | #include <iprt/errcore.h>
|
---|
35 | #include <iprt/initterm.h>
|
---|
36 | #include <iprt/file.h>
|
---|
37 | #include <VBox/log.h>
|
---|
38 | #include <iprt/stream.h>
|
---|
39 | #include <iprt/string.h>
|
---|
40 | #include <iprt/semaphore.h>
|
---|
41 | #include <iprt/thread.h>
|
---|
42 |
|
---|
43 | #include <errno.h>
|
---|
44 | #include <poll.h>
|
---|
45 | #include <string.h>
|
---|
46 | #include <unistd.h>
|
---|
47 |
|
---|
48 | #include <fcntl.h>
|
---|
49 |
|
---|
50 | #include <linux/limits.h>
|
---|
51 |
|
---|
52 | /* Workaround for <sys/cdef.h> defining __flexarr to [] which beats us in
|
---|
53 | * struct inotify_event (char name __flexarr). */
|
---|
54 | #include <sys/cdefs.h>
|
---|
55 | #undef __flexarr
|
---|
56 | #define __flexarr [RT_FLEXIBLE_ARRAY]
|
---|
57 | #include <sys/inotify.h>
|
---|
58 | #include <sys/types.h>
|
---|
59 | #include <sys/socket.h>
|
---|
60 | #include <sys/stat.h>
|
---|
61 |
|
---|
62 | #include "../HostDnsService.h"
|
---|
63 |
|
---|
64 |
|
---|
65 | /*********************************************************************************************************************************
|
---|
66 | * Global Variables *
|
---|
67 | *********************************************************************************************************************************/
|
---|
68 | static const char g_szEtcFolder[] = "/etc";
|
---|
69 | static const char g_szResolvConfPath[] = "/etc/resolv.conf";
|
---|
70 | static const char g_szResolvConfFilename[] = "resolv.conf";
|
---|
71 |
|
---|
72 |
|
---|
73 | HostDnsServiceLinux::~HostDnsServiceLinux()
|
---|
74 | {
|
---|
75 | if (m_fdShutdown >= 0)
|
---|
76 | {
|
---|
77 | close(m_fdShutdown);
|
---|
78 | m_fdShutdown = -1;
|
---|
79 | }
|
---|
80 | }
|
---|
81 |
|
---|
82 | HRESULT HostDnsServiceLinux::init(HostDnsMonitorProxy *pProxy)
|
---|
83 | {
|
---|
84 | return HostDnsServiceResolvConf::init(pProxy, "/etc/resolv.conf");
|
---|
85 | }
|
---|
86 |
|
---|
87 | int HostDnsServiceLinux::monitorThreadShutdown(RTMSINTERVAL uTimeoutMs)
|
---|
88 | {
|
---|
89 | RT_NOREF(uTimeoutMs);
|
---|
90 |
|
---|
91 | if (m_fdShutdown >= 0)
|
---|
92 | send(m_fdShutdown, "", 1, MSG_NOSIGNAL);
|
---|
93 |
|
---|
94 | return VINF_SUCCESS;
|
---|
95 | }
|
---|
96 |
|
---|
97 | /**
|
---|
98 | * Format the notifcation event mask into a buffer for logging purposes.
|
---|
99 | */
|
---|
100 | static const char *InotifyMaskToStr(char *psz, size_t cb, uint32_t fMask)
|
---|
101 | {
|
---|
102 | static struct { const char *pszName; uint32_t cchName, fFlag; } const s_aFlags[] =
|
---|
103 | {
|
---|
104 | # define ENTRY(fFlag) { #fFlag, sizeof(#fFlag) - 1, fFlag }
|
---|
105 | ENTRY(IN_ACCESS),
|
---|
106 | ENTRY(IN_MODIFY),
|
---|
107 | ENTRY(IN_ATTRIB),
|
---|
108 | ENTRY(IN_CLOSE_WRITE),
|
---|
109 | ENTRY(IN_CLOSE_NOWRITE),
|
---|
110 | ENTRY(IN_OPEN),
|
---|
111 | ENTRY(IN_MOVED_FROM),
|
---|
112 | ENTRY(IN_MOVED_TO),
|
---|
113 | ENTRY(IN_CREATE),
|
---|
114 | ENTRY(IN_DELETE),
|
---|
115 | ENTRY(IN_DELETE_SELF),
|
---|
116 | ENTRY(IN_MOVE_SELF),
|
---|
117 | ENTRY(IN_Q_OVERFLOW),
|
---|
118 | ENTRY(IN_IGNORED),
|
---|
119 | ENTRY(IN_UNMOUNT),
|
---|
120 | ENTRY(IN_ISDIR),
|
---|
121 | };
|
---|
122 | size_t offDst = 0;
|
---|
123 | for (size_t i = 0; i < RT_ELEMENTS(s_aFlags); i++)
|
---|
124 | if (fMask & s_aFlags[i].fFlag)
|
---|
125 | {
|
---|
126 | if (offDst && offDst < cb)
|
---|
127 | psz[offDst++] = ' ';
|
---|
128 | if (offDst < cb)
|
---|
129 | {
|
---|
130 | size_t cbToCopy = RT_MIN(s_aFlags[i].cchName, cb - offDst);
|
---|
131 | memcpy(&psz[offDst], s_aFlags[i].pszName, cbToCopy);
|
---|
132 | offDst += cbToCopy;
|
---|
133 | }
|
---|
134 |
|
---|
135 | fMask &= ~s_aFlags[i].fFlag;
|
---|
136 | if (!fMask)
|
---|
137 | break;
|
---|
138 | }
|
---|
139 | if (fMask && offDst < cb)
|
---|
140 | RTStrPrintf(&psz[offDst], cb - offDst, offDst ? " %#x" : "%#x", fMask);
|
---|
141 | else
|
---|
142 | psz[RT_MIN(offDst, cb - 1)] = '\0';
|
---|
143 | return psz;
|
---|
144 | }
|
---|
145 |
|
---|
146 | /**
|
---|
147 | * Helper for HostDnsServiceLinux::monitorThreadProc.
|
---|
148 | */
|
---|
149 | static int monitorSymlinkedDir(int iInotifyFd, char szRealResolvConf[PATH_MAX], size_t *poffFilename)
|
---|
150 | {
|
---|
151 | RT_BZERO(szRealResolvConf, PATH_MAX);
|
---|
152 |
|
---|
153 | /* Check that it's a symlink first. */
|
---|
154 | struct stat st;
|
---|
155 | if ( lstat(g_szResolvConfPath, &st) >= 0
|
---|
156 | && S_ISLNK(st.st_mode))
|
---|
157 | {
|
---|
158 | /* If realpath fails, the file must've been deleted while we were busy: */
|
---|
159 | if ( realpath(g_szResolvConfPath, szRealResolvConf)
|
---|
160 | && strchr(szRealResolvConf, '/'))
|
---|
161 | {
|
---|
162 | /* Cut of the filename part. We only need that for deletion checks and such. */
|
---|
163 | size_t const offFilename = strrchr(szRealResolvConf, '/') - &szRealResolvConf[0];
|
---|
164 | *poffFilename = offFilename + 1;
|
---|
165 | szRealResolvConf[offFilename] = '\0';
|
---|
166 |
|
---|
167 | /* Try set up directory monitoring. (File monitoring is done via the symlink.) */
|
---|
168 | return inotify_add_watch(iInotifyFd, szRealResolvConf, IN_MOVE | IN_CREATE | IN_DELETE);
|
---|
169 | }
|
---|
170 | }
|
---|
171 |
|
---|
172 | *poffFilename = 0;
|
---|
173 | szRealResolvConf[0] = '\0';
|
---|
174 | return -1;
|
---|
175 | }
|
---|
176 |
|
---|
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. */
|
---|
180 | int HostDnsServiceLinux::monitorThreadProc(void)
|
---|
181 | {
|
---|
182 | /*
|
---|
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 iRc = socketpair(AF_LOCAL, SOCK_DGRAM | SOCK_CLOEXEC, 0, aiStopPair);
|
---|
188 | int iErr = errno;
|
---|
189 | AssertLogRelMsgReturn(iRc == 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).
|
---|
198 | *
|
---|
199 | * Note! Ignoring failures here is safe, because poll will ignore entires
|
---|
200 | * with negative fd values.
|
---|
201 | */
|
---|
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
|
---|
207 | involving /etc/resolv.conf: */
|
---|
208 | int const iWdDir = inotify_add_watch(iNotifyFd, g_szEtcFolder, IN_MOVE | IN_CREATE | IN_DELETE);
|
---|
209 |
|
---|
210 | /* In case g_szResolvConfPath is a symbolic link, monitor the target directory
|
---|
211 | too for changes to what it links to (kept up to date via iWdDir). */
|
---|
212 | char szRealResolvConf[PATH_MAX];
|
---|
213 | size_t offRealResolvConfName = 0;
|
---|
214 | int iWdSymDir = ::monitorSymlinkedDir(iNotifyFd, szRealResolvConf, &offRealResolvConfName);
|
---|
215 |
|
---|
216 | /* Monitor the resolv.conf itself if it exists, following all symlinks. */
|
---|
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));
|
---|
221 |
|
---|
222 | /*
|
---|
223 | * poll initialization:
|
---|
224 | */
|
---|
225 | pollfd aFdPolls[2];
|
---|
226 | RT_ZERO(aFdPolls);
|
---|
227 |
|
---|
228 | aFdPolls[0].fd = iNotifyFd;
|
---|
229 | aFdPolls[0].events = POLLIN;
|
---|
230 |
|
---|
231 | aFdPolls[1].fd = aiStopPair[1];
|
---|
232 | aFdPolls[1].events = POLLIN;
|
---|
233 |
|
---|
234 | /*
|
---|
235 | * The monitoring loop.
|
---|
236 | */
|
---|
237 | int vrcRet = VINF_SUCCESS;
|
---|
238 | for (;;)
|
---|
239 | {
|
---|
240 | /*
|
---|
241 | * Wait for something to happen.
|
---|
242 | */
|
---|
243 | iRc = poll(aFdPolls, RT_ELEMENTS(aFdPolls), -1 /*infinite timeout*/);
|
---|
244 | if (iRc == -1)
|
---|
245 | {
|
---|
246 | if (errno != EINTR)
|
---|
247 | {
|
---|
248 | LogRelMax(32, ("HostDnsServiceLinux::monitorThreadProc: poll failed %d: errno=%d\n", iRc, errno));
|
---|
249 | RTThreadSleep(1);
|
---|
250 | }
|
---|
251 | continue;
|
---|
252 | }
|
---|
253 | Log5Func(("poll returns %d: [0]=%#x [1]=%#x\n", iRc, aFdPolls[1].revents, aFdPolls[0].revents));
|
---|
254 |
|
---|
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);
|
---|
260 |
|
---|
261 | /*
|
---|
262 | * Check for shutdown first.
|
---|
263 | */
|
---|
264 | if (aFdPolls[1].revents & POLLIN)
|
---|
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). */
|
---|
268 |
|
---|
269 | if (aFdPolls[0].revents & POLLIN)
|
---|
270 | {
|
---|
271 | /*
|
---|
272 | * Read the notification event.
|
---|
273 | */
|
---|
274 | #define INOTIFY_EVENT_SIZE (RT_UOFFSETOF(struct inotify_event, name))
|
---|
275 | union
|
---|
276 | {
|
---|
277 | uint8_t abBuf[(INOTIFY_EVENT_SIZE * 2 - 1 + NAME_MAX) / INOTIFY_EVENT_SIZE * INOTIFY_EVENT_SIZE * 4];
|
---|
278 | uint64_t uAlignTrick[2];
|
---|
279 | } uEvtBuf;
|
---|
280 |
|
---|
281 | ssize_t cbEvents = read(iNotifyFd, &uEvtBuf, sizeof(uEvtBuf));
|
---|
282 | Log5Func(("read(inotify) -> %zd\n", cbEvents));
|
---|
283 | if (cbEvents > 0)
|
---|
284 | Log5(("%.*Rhxd\n", cbEvents, &uEvtBuf));
|
---|
285 |
|
---|
286 | /*
|
---|
287 | * Process the events.
|
---|
288 | *
|
---|
289 | * We'll keep the old watch descriptor number till after we're done
|
---|
290 | * parsing this block of events. Even so, the removal of watches
|
---|
291 | * isn't race free, as they'll get automatically removed when what
|
---|
292 | * is being watched is unliked.
|
---|
293 | */
|
---|
294 | int iWdFileNew = iWdFile;
|
---|
295 | int iWdSymDirNew = iWdSymDir;
|
---|
296 | bool fTryReRead = false;
|
---|
297 | struct inotify_event const *pCurEvt = (struct inotify_event const *)&uEvtBuf;
|
---|
298 | while (cbEvents >= (ssize_t)INOTIFY_EVENT_SIZE)
|
---|
299 | {
|
---|
300 | char szTmp[64];
|
---|
301 | if (pCurEvt->len == 0)
|
---|
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));
|
---|
304 | else
|
---|
305 | LogRel5(("HostDnsServiceLinux::monitorThreadProc: event: wd=%#x mask=%#x (%s) cookie=%#x len=%#x '%s'\n",
|
---|
306 | pCurEvt->wd, pCurEvt->mask, InotifyMaskToStr(szTmp, sizeof(szTmp), pCurEvt->mask),
|
---|
307 | pCurEvt->cookie, pCurEvt->len, pCurEvt->name));
|
---|
308 |
|
---|
309 | /*
|
---|
310 | * The file itself (symlinks followed, remember):
|
---|
311 | */
|
---|
312 | if (pCurEvt->wd == iWdFile)
|
---|
313 | {
|
---|
314 | if (pCurEvt->mask & IN_CLOSE_WRITE)
|
---|
315 | {
|
---|
316 | Log5Func(("file: close-after-write => trigger re-read\n"));
|
---|
317 | fTryReRead = true;
|
---|
318 | }
|
---|
319 | else if (pCurEvt->mask & IN_DELETE_SELF)
|
---|
320 | {
|
---|
321 | Log5Func(("file: deleted self\n"));
|
---|
322 | if (iWdFileNew != -1)
|
---|
323 | {
|
---|
324 | iRc = inotify_rm_watch(iNotifyFd, iWdFileNew);
|
---|
325 | AssertMsg(iRc >= 0, ("%d/%d\n", iRc, errno));
|
---|
326 | iWdFileNew = -1;
|
---|
327 | }
|
---|
328 | }
|
---|
329 | else if (pCurEvt->mask & IN_IGNORED)
|
---|
330 | iWdFileNew = -1; /* file deleted */
|
---|
331 | else
|
---|
332 | AssertMsgFailed(("file: mask=%#x\n", pCurEvt->mask));
|
---|
333 | }
|
---|
334 | /*
|
---|
335 | * The /etc directory
|
---|
336 | *
|
---|
337 | * We only care about events relating to the creation, deletion and
|
---|
338 | * renaming of 'resolv.conf'. We'll restablish both the direct file
|
---|
339 | * watching and the watching of any symlinked directory on all of
|
---|
340 | * these events, although for the former we'll delay the re-starting
|
---|
341 | * of the watching till all events have been processed.
|
---|
342 | */
|
---|
343 | else if (pCurEvt->wd == iWdDir)
|
---|
344 | {
|
---|
345 | if ( pCurEvt->len > 0
|
---|
346 | && strcmp(g_szResolvConfFilename, pCurEvt->name) == 0)
|
---|
347 | {
|
---|
348 | if (pCurEvt->mask & (IN_MOVE | IN_CREATE | IN_DELETE))
|
---|
349 | {
|
---|
350 | if (iWdFileNew >= 0)
|
---|
351 | {
|
---|
352 | iRc = inotify_rm_watch(iNotifyFd, iWdFileNew);
|
---|
353 | Log5Func(("dir: moved / created / deleted: dropped file watch (%d - iRc=%d/err=%d)\n",
|
---|
354 | iWdFileNew, iRc, errno));
|
---|
355 | iWdFileNew = -1;
|
---|
356 | }
|
---|
357 | if (iWdSymDirNew >= 0)
|
---|
358 | {
|
---|
359 | iRc = inotify_rm_watch(iNotifyFd, iWdSymDirNew);
|
---|
360 | Log5Func(("dir: moved / created / deleted: dropped symlinked dir watch (%d - %s/%s - iRc=%d/err=%d)\n",
|
---|
361 | iWdSymDirNew, szRealResolvConf, &szRealResolvConf[offRealResolvConfName], iRc, errno));
|
---|
362 | iWdSymDirNew = -1;
|
---|
363 | offRealResolvConfName = 0;
|
---|
364 | }
|
---|
365 | if (pCurEvt->mask & (IN_MOVED_TO | IN_CREATE))
|
---|
366 | {
|
---|
367 | Log5Func(("dir: moved_to / created: trigger re-read\n"));
|
---|
368 | fTryReRead = true;
|
---|
369 |
|
---|
370 | iWdSymDirNew = ::monitorSymlinkedDir(iNotifyFd, szRealResolvConf, &offRealResolvConfName);
|
---|
371 | if (iWdSymDirNew < 0)
|
---|
372 | Log5Func(("dir: moved_to / created: re-stablished symlinked-directory monitoring: iWdSymDir=%d (%s/%s)\n",
|
---|
373 | iWdSymDirNew, szRealResolvConf, &szRealResolvConf[offRealResolvConfName]));
|
---|
374 | }
|
---|
375 | }
|
---|
376 | else
|
---|
377 | AssertMsgFailed(("dir: %#x\n", pCurEvt->mask));
|
---|
378 | }
|
---|
379 | }
|
---|
380 | /*
|
---|
381 | * The directory of a symlinked resolv.conf.
|
---|
382 | *
|
---|
383 | * Where we only care when the symlink target is created, moved_to,
|
---|
384 | * deleted or moved_from - i.e. a minimal version of the /etc event
|
---|
385 | * processing above.
|
---|
386 | *
|
---|
387 | * Note! Since we re-statablish monitoring above, szRealResolvConf
|
---|
388 | * might not match the event we're processing. Fortunately,
|
---|
389 | * this shouldn't be important except for debug logging.
|
---|
390 | */
|
---|
391 | else if (pCurEvt->wd == iWdSymDir)
|
---|
392 | {
|
---|
393 | if ( pCurEvt->len > 0
|
---|
394 | && offRealResolvConfName > 0
|
---|
395 | && strcmp(&szRealResolvConf[offRealResolvConfName], pCurEvt->name) == 0)
|
---|
396 | {
|
---|
397 | if (iWdFileNew >= 0)
|
---|
398 | {
|
---|
399 | iRc = inotify_rm_watch(iNotifyFd, iWdFileNew);
|
---|
400 | Log5Func(("symdir: moved / created / deleted: drop file watch (%d - iRc=%d/err=%d)\n",
|
---|
401 | iWdFileNew, iRc, errno));
|
---|
402 | iWdFileNew = -1;
|
---|
403 | }
|
---|
404 | if (pCurEvt->mask & (IN_MOVED_TO | IN_CREATE))
|
---|
405 | {
|
---|
406 | Log5Func(("symdir: moved_to / created: trigger re-read\n"));
|
---|
407 | fTryReRead = true;
|
---|
408 | }
|
---|
409 | }
|
---|
410 | }
|
---|
411 | /* We can get here it seems if our inotify_rm_watch calls above takes
|
---|
412 | place after new events relating to the two descriptors happens. */
|
---|
413 | else
|
---|
414 | Log5Func(("Unknown (obsoleted) wd value: %d (mask=%#x cookie=%#x len=%#x)\n",
|
---|
415 | pCurEvt->wd, pCurEvt->mask, pCurEvt->cookie, pCurEvt->len));
|
---|
416 |
|
---|
417 | /* advance to the next event */
|
---|
418 | Assert(pCurEvt->len / INOTIFY_EVENT_SIZE * INOTIFY_EVENT_SIZE == pCurEvt->len);
|
---|
419 | size_t const cbCurEvt = INOTIFY_EVENT_SIZE + pCurEvt->len;
|
---|
420 | pCurEvt = (struct inotify_event const *)((uintptr_t)pCurEvt + cbCurEvt);
|
---|
421 | cbEvents -= cbCurEvt;
|
---|
422 | }
|
---|
423 |
|
---|
424 | /*
|
---|
425 | * Commit the new watch descriptor numbers now that we're
|
---|
426 | * done processing event using the old ones.
|
---|
427 | */
|
---|
428 | iWdFile = iWdFileNew;
|
---|
429 | iWdSymDir = iWdSymDirNew;
|
---|
430 |
|
---|
431 | /*
|
---|
432 | * If the resolv.conf watch descriptor is -1, try restablish it here.
|
---|
433 | */
|
---|
434 | if (iWdFile == -1)
|
---|
435 | {
|
---|
436 | iWdFile = inotify_add_watch(iNotifyFd, g_szResolvConfPath, IN_CLOSE_WRITE | IN_DELETE_SELF);
|
---|
437 | if (iWdFile >= 0)
|
---|
438 | {
|
---|
439 | Log5Func(("Re-established file watcher: iWdFile=%d\n", iWdFile));
|
---|
440 | fTryReRead = true;
|
---|
441 | }
|
---|
442 | }
|
---|
443 |
|
---|
444 | /*
|
---|
445 | * If any of the events indicate that we should re-read the file, we
|
---|
446 | * do so now. Should reduce number of unnecessary re-reads.
|
---|
447 | */
|
---|
448 | if (fTryReRead)
|
---|
449 | {
|
---|
450 | Log5Func(("Calling readResolvConf()...\n"));
|
---|
451 | try
|
---|
452 | {
|
---|
453 | readResolvConf();
|
---|
454 | }
|
---|
455 | catch (...)
|
---|
456 | {
|
---|
457 | LogRel(("HostDnsServiceLinux::monitorThreadProc: readResolvConf threw exception!\n"));
|
---|
458 | }
|
---|
459 | }
|
---|
460 | }
|
---|
461 | }
|
---|
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 | LogRel5(("HostDnsServiceLinux::monitorThreadProc: returns %Rrc\n", vrcRet));
|
---|
474 | return vrcRet;
|
---|
475 | }
|
---|
476 |
|
---|