Changeset 98071 in vbox for trunk/src/VBox/Main/src-server
- Timestamp:
- Jan 13, 2023 10:38:26 AM (2 years ago)
- svn:sync-xref-src-repo-rev:
- 155196
- Location:
- trunk/src/VBox/Main/src-server
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-server/HostDnsService.h
r96407 r98071 249 249 public: 250 250 251 HostDnsServiceLinux() : HostDnsServiceResolvConf(true) {}251 HostDnsServiceLinux() : HostDnsServiceResolvConf(true), m_fdShutdown(-1) {} 252 252 virtual ~HostDnsServiceLinux(); 253 253 … … 260 260 int monitorThreadShutdown(RTMSINTERVAL uTimeoutMs); 261 261 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; 262 266 }; 263 267 -
trunk/src/VBox/Main/src-server/linux/HostDnsServiceLinux.cpp
r98068 r98071 66 66 * Global Variables * 67 67 *********************************************************************************************************************************/ 68 static int g_DnsMonitorStop[2];69 70 68 static const char g_szEtcFolder[] = "/etc"; 71 69 static const char g_szResolvConfPath[] = "/etc/resolv.conf"; … … 73 71 74 72 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); 73 HostDnsServiceLinux::~HostDnsServiceLinux() 74 { 75 if (m_fdShutdown >= 0) 76 { 77 close(m_fdShutdown); 78 m_fdShutdown = -1; 85 79 } 86 87 int fileDescriptor() const {return fd;}88 89 protected:90 int fd;91 };92 93 94 class AutoNotify : public FileDescriptor95 {96 public:97 AutoNotify()98 {99 FileDescriptor::fd = inotify_init();100 AssertReturnVoid(FileDescriptor::fd != -1);101 }102 };103 104 HostDnsServiceLinux::~HostDnsServiceLinux()105 {106 80 } 107 81 … … 115 89 RT_NOREF(uTimeoutMs); 116 90 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 120 94 return VINF_SUCCESS; 121 95 } 122 96 123 #ifdef LOG_ENABLED124 97 /** 125 98 * Format the notifcation event mask into a buffer for logging purposes. … … 170 143 return psz; 171 144 } 172 #endif173 174 145 175 146 /** … … 204 175 } 205 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. */ 206 180 int HostDnsServiceLinux::monitorThreadProc(void) 207 181 { 208 182 /* 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). 212 198 * 213 199 * Note! Ignoring failures here is safe, because poll will ignore entires 214 200 * with negative fd values. 215 201 */ 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 219 207 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); 221 209 222 210 /* 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). */ 224 212 char szRealResolvConf[PATH_MAX]; 225 213 size_t offRealResolvConfName = 0; 226 int iWdSymDir = ::monitorSymlinkedDir( Notify.fileDescriptor(), szRealResolvConf, &offRealResolvConfName);214 int iWdSymDir = ::monitorSymlinkedDir(iNotifyFd, szRealResolvConf, &offRealResolvConfName); 227 215 228 216 /* 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)); 242 221 243 222 /* … … 247 226 RT_ZERO(aFdPolls); 248 227 249 aFdPolls[0].fd = Notify.fileDescriptor();228 aFdPolls[0].fd = iNotifyFd; 250 229 aFdPolls[0].events = POLLIN; 251 230 252 aFdPolls[1].fd = g_DnsMonitorStop[1];231 aFdPolls[1].fd = aiStopPair[1]; 253 232 aFdPolls[1].events = POLLIN; 254 255 onMonitorThreadInitDone();256 233 257 234 /* 258 235 * The monitoring loop. 259 236 */ 237 int vrcRet = VINF_SUCCESS; 260 238 for (;;) 261 239 { … … 266 244 if (rc == -1) 267 245 { 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 } 270 251 continue; 271 252 } 272 253 Log5Func(("poll returns %d: [0]=%#x [1]=%#x\n", rc, aFdPolls[1].revents, aFdPolls[0].revents)); 273 254 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); 277 260 278 261 /* … … 280 263 */ 281 264 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). */ 283 268 284 269 if (aFdPolls[0].revents & POLLIN) … … 294 279 } uEvtBuf; 295 280 296 ssize_t cbEvents = read( Notify.fileDescriptor(), &uEvtBuf, sizeof(uEvtBuf));281 ssize_t cbEvents = read(iNotifyFd, &uEvtBuf, sizeof(uEvtBuf)); 297 282 Log5Func(("read(inotify) -> %zd\n", cbEvents)); 298 283 if (cbEvents > 0) … … 313 298 while (cbEvents >= (ssize_t)INOTIFY_EVENT_SIZE) 314 299 { 315 #ifdef LOG_ENABLED316 300 char szTmp[64]; 317 301 if (pCurEvt->len == 0) 318 Log 5Func(("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)); 320 304 else 321 Log 5Func(("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", 322 306 pCurEvt->wd, pCurEvt->mask, InotifyMaskToStr(szTmp, sizeof(szTmp), pCurEvt->mask), 323 307 pCurEvt->cookie, pCurEvt->len, pCurEvt->name)); 324 #endif325 308 326 309 /* … … 339 322 if (iWdFileNew != -1) 340 323 { 341 rc = inotify_rm_watch( Notify.fileDescriptor(), iWdFileNew);324 rc = inotify_rm_watch(iNotifyFd, iWdFileNew); 342 325 AssertMsg(rc >= 0, ("%d/%d\n", rc, errno)); 343 326 iWdFileNew = -1; … … 367 350 if (iWdFileNew >= 0) 368 351 { 369 rc = inotify_rm_watch( Notify.fileDescriptor(), iWdFileNew);352 rc = inotify_rm_watch(iNotifyFd, iWdFileNew); 370 353 Log5Func(("dir: moved / created / deleted: dropped file watch (%d - rc=%d/err=%d)\n", 371 354 iWdFileNew, rc, errno)); … … 374 357 if (iWdSymDirNew >= 0) 375 358 { 376 rc = inotify_rm_watch( Notify.fileDescriptor(), iWdSymDirNew);359 rc = inotify_rm_watch(iNotifyFd, iWdSymDirNew); 377 360 Log5Func(("dir: moved / created / deleted: dropped symlinked dir watch (%d - %s/%s - rc=%d/err=%d)\n", 378 361 iWdSymDirNew, szRealResolvConf, &szRealResolvConf[offRealResolvConfName], rc, errno)); … … 385 368 fTryReRead = true; 386 369 387 iWdSymDirNew = ::monitorSymlinkedDir(Notify.fileDescriptor(), 388 szRealResolvConf, &offRealResolvConfName); 370 iWdSymDirNew = ::monitorSymlinkedDir(iNotifyFd, szRealResolvConf, &offRealResolvConfName); 389 371 if (iWdSymDirNew < 0) 390 372 Log5Func(("dir: moved_to / created: re-stablished symlinked-directory monitoring: iWdSymDir=%d (%s/%s)\n", … … 415 397 if (iWdFileNew >= 0) 416 398 { 417 rc = inotify_rm_watch( Notify.fileDescriptor(), iWdFileNew);399 rc = inotify_rm_watch(iNotifyFd, iWdFileNew); 418 400 Log5Func(("symdir: moved / created / deleted: drop file watch (%d - rc=%d/err=%d)\n", 419 401 iWdFileNew, rc, errno)); … … 452 434 if (iWdFile == -1) 453 435 { 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); 455 437 if (iWdFile >= 0) 456 438 { … … 467 449 { 468 450 Log5Func(("Calling readResolvConf()...\n")); 469 readResolvConf(); 451 try 452 { 453 readResolvConf(); 454 } 455 catch (...) 456 { 457 LogRel(("HostDnsServiceLinux::monitorThreadProc: readResolvConf threw exception!\n")); 458 } 470 459 } 471 460 } 472 461 } 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.