Fix to tap reset code in Windows tap connector.

This commit is contained in:
Adam Ierymenko 2015-05-08 16:49:08 -07:00
parent e744580b89
commit 241f308334

View File

@ -92,10 +92,8 @@ static const WindowsEthernetTapEnv WINENV;
// Only create or delete devices one at a time // Only create or delete devices one at a time
static Mutex _systemTapInitLock; static Mutex _systemTapInitLock;
// Set to true if existing taps should close and reopen due to new device creation // Incrementing this causes everyone currently open to close and reopen
// This is a hack to get around what seems to be a bug that causes existing static volatile int _systemTapResetStatus = 0;
// devices to go into a coma after new device creation.
static volatile bool _needReset = false;
} // anonymous namespace } // anonymous namespace
@ -271,8 +269,11 @@ WindowsEthernetTap::WindowsEthernetTap(
} else break; // no more keys or error occurred } else break; // no more keys or error occurred
} }
// Cause all existing taps to reset // When we create a new tap device from scratch, existing taps for
_needReset = true; // some reason go into 'unplugged' state. This can be fixed by
// closing and re-opening them. Incrementing this causes all
// existing tap threads to do this.
++_systemTapResetStatus;
} }
if (_netCfgInstanceId.length() > 0) { if (_netCfgInstanceId.length() > 0) {
@ -592,6 +593,7 @@ void WindowsEthernetTap::threadMain()
} }
Utils::snprintf(tapPath,sizeof(tapPath),"\\\\.\\Global\\%s.tap",_netCfgInstanceId.c_str()); Utils::snprintf(tapPath,sizeof(tapPath),"\\\\.\\Global\\%s.tap",_netCfgInstanceId.c_str());
int prevTapResetStatus = _systemTapResetStatus;
while (_run) { while (_run) {
_tap = CreateFileA(tapPath,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_SYSTEM|FILE_FLAG_OVERLAPPED,NULL); _tap = CreateFileA(tapPath,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_SYSTEM|FILE_FLAG_OVERLAPPED,NULL);
if (_tap == INVALID_HANDLE_VALUE) { if (_tap == INVALID_HANDLE_VALUE) {
@ -695,7 +697,11 @@ void WindowsEthernetTap::threadMain()
ReadFile(_tap,tapReadBuf,sizeof(tapReadBuf),NULL,&tapOvlRead); ReadFile(_tap,tapReadBuf,sizeof(tapReadBuf),NULL,&tapOvlRead);
bool writeInProgress = false; bool writeInProgress = false;
while ((_run)&&(!_needReset)) { while (_run) {
if (prevTapResetStatus != _systemTapResetStatus) {
prevTapResetStatus = _systemTapResetStatus;
break; // this will cause us to close and reopen the tap
}
DWORD r = WaitForMultipleObjectsEx(writeInProgress ? 3 : 2,wait4,FALSE,2500,TRUE); DWORD r = WaitForMultipleObjectsEx(writeInProgress ? 3 : 2,wait4,FALSE,2500,TRUE);
if (!_run) break; // will also break outer while(_run) if (!_run) break; // will also break outer while(_run)