Changeset 50263 in vbox for trunk/src/VBox/Main/src-server/linux
- Timestamp:
- Jan 28, 2014 7:29:52 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-server/linux/HostDnsServiceLinux.cpp
r49460 r50263 33 33 #include <fcntl.h> 34 34 35 #include <linux/limits.h> 36 35 37 #include <sys/inotify.h> 36 38 #include <sys/types.h> … … 42 44 43 45 44 static RTTHREAD g_DnsMonitoringThread;45 static RTSEMEVENT g_DnsInitEvent;46 46 static int g_DnsMonitorStop[2]; 47 48 static const std::string g_EtcFolder = "/etc"; 49 static const std::string g_ResolvConf = "resolv.conf"; 50 static const std::string g_ResolvConfFullPath = "/etc/resolv.conf"; 47 51 48 52 class FileDescriptor … … 71 75 AssertReturnVoid(FileDescriptor::fd != -1); 72 76 } 73 74 77 }; 75 78 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; 79 struct InotifyEventWithName 80 { 81 struct inotify_event e; 82 char name[NAME_MAX]; 102 83 }; 103 84 104 105 85 HostDnsServiceLinux::~HostDnsServiceLinux() 106 86 { 107 send(g_DnsMonitorStop[0], "", 1, 0);87 monitorThreadShutdown(); 108 88 } 109 89 110 90 111 int HostDnsServiceLinux:: hostMonitoringRoutine(RTTHREAD ThreadSelf, void *pvUser)112 { 113 NOREF(ThreadSelf); 91 int HostDnsServiceLinux::monitorWorker() 92 { 93 114 94 AutoNotify a; 115 HostDnsServiceLinux *dns = static_cast<HostDnsServiceLinux *>(pvUser);116 AutoWatcher w(a, std::string(dns->resolvConf().c_str()));117 95 118 96 int rc = socketpair(AF_LOCAL, SOCK_DGRAM, 0, g_DnsMonitorStop); … … 131 109 polls[1].events = POLLIN; 132 110 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; 135 131 while(true) 136 132 { … … 148 144 if (polls[0].revents & POLLIN) 149 145 { 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 } 159 225 } 160 226 } … … 162 228 163 229 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; 230 void HostDnsServiceLinux::monitorThreadShutdown() 231 { 232 send(g_DnsMonitorStop[0], "", 1, 0); 179 233 }
Note:
See TracChangeset
for help on using the changeset viewer.