Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];

Вниз

Spurious wakeup в WinSock?   Найти похожие ветки 

 
ProgRAMmer Dimonych ©   (2012-08-01 14:31) [0]

Столкнулся со следующей ситуацией.

Есть приложение, которое активно работает с сетью. Один из его потоков работает так:

1. socket(...)
2. WSACreateEvent() + WSAEventSelect(FD_CONNECT | FD_READ | FD_CLOSE)
3. connect()
4. WSAWaitForMultipleEvents(1, hEvent)
5. WSAEnumNetworkEvents()

Достаточно часто стала наблюдаться ситуация, когда Wait возвращает WSA_WAIT_OBJECT_0, а EnumNetworkEvents возвращает обнулённое поле lNetworkEvents, т.е. типа "событий не было". Трейсы и API Monitor подтверждают.

Гугл выдаёт ссылки на несколько форумов, но ничего конкретного там найти не удалось. На тестовом приложении (однопоточном) проблема не повторяется, в исходном проекте проблемный код полностью изолирован от других потоков (переменные локальные, вся указанная логика - в отдельном потоке).

Собственно, вопрос: сталкивался ли кто-нибудь с таким. Любые рассуждения по теме приветствуются.

P.S. Сам пока активно ищу ошибки в программе, но уже пошли в ход самые безумные предположения.


 
Вариант   (2012-08-01 15:30) [1]

Где код этого хозяйства?


> ProgRAMmer Dimonych ©   (01.08.12 14:31)



> 1. socket(...)
> 2. WSACreateEvent() + WSAEventSelect(FD_CONNECT | FD_READ
> | FD_CLOSE)
> 3. connect()
> 4. WSAWaitForMultipleEvents(1, hEvent)
> 5. WSAEnumNetworkEvents()


 
Сергей М. ©   (2012-08-01 15:58) [2]


> Любые рассуждения по теме приветствуются


WSACreateEvent принципиально ничем не отличается от CreateEvent, т.е. возвращает хендл event-объекта, который м.б. использован в любых wait-вызовах общего назначение, не только в WSAWait.

По этой причине WSAWaitForMultipleEvents вполне может вернуть WAIT_OBJECT_0, если ей подсунули любой другой сигналящий event-объект, не имеющий ничего общего с тем который был создан при WSACreateEvent.

Это наводит на мысль что в период времени между п.2 и п.4 область данных, распределенных под хранение хендла, созданного тобой при WSACreateEvent, была неосознанно затерта и перезаписана значением хендла совсем другого существующего event-объекта, который на момент п.4 находился или перешел в сигнальное состояние, что и вызвало WAIT_OBJECT_0.

При этом если ф-ция в п.5 гарантированно вернула не SOCKET_ERROR, значит ей передан правильный, но не просигналивший на самом деле хендл.


 
ProgRAMmer Dimonych ©   (2012-08-01 18:03) [3]

> [1] Вариант   (01.08.12 15:30)
> Где код этого хозяйства?

С кодом не всё просто: часть одного из модулей защиты, теоретически коммерческая тайна. Если убрать все подробности, то что-то типа такого получится:

...
if (SOCKET_ERROR == WSAEventSelect(ConnectSock, hEvent, FD_CONNECT | FD_READ | FD_CLOSE))
break;
Result = ConnectWithTimeout(ConnectSock, hEvent, (LPSOCKADDR)AgentAddr, sizeof(SOCKADDR_STORAGE), dwTimeout);
if (ERR_GOODRET != Result)
break;
...

int CWSMonitor::ConnectWithTimeout(SOCKET s, WSAEVENT hConnectEvent, SOCKADDR *name, int namelen, DWORD Timeout)
{
int Result = 0;

while (TRUE)
{
 ResetEvent(hConnectEvent);
 if (SOCKET_ERROR == connect(s, name, namelen))
 {
  Result = WSAGetLastError();
  if (WSAEWOULDBLOCK != Result)
   break;
 }
 Result = WSAWaitForMultipleEvents(1, &hConnectEvent, TRUE, Timeout, FALSE);
 if (WSA_WAIT_EVENT_0 != Result)
  break;

 WSANETWORKEVENTS Events;
 ZeroMemory(&Events, sizeof(Events));
 if (SOCKET_ERROR == WSAEnumNetworkEvents(s, hConnectEvent, &Events))
 {
  Result = WSAGetLastError();
  break;
 }
 if (Events.lNetworkEvents == 0)
 {
  TRACE("===== Spurious wakeup! =====");
 }
 if (Events.lNetworkEvents & FD_CLOSE)
 {
  Result = WSAECONNREFUSED;
  break;
 }

 Result = Events.iErrorCode[FD_CONNECT_BIT];
 break;
}

return Result;
}


hEvent - локальная переменная в вызывающем методе (приведён частично). ConnectSock - копия значения поля класса, передаётся параметром метода.


 
ProgRAMmer Dimonych ©   (2012-08-01 18:06) [4]

> [2] Сергей М. ©   (01.08.12 15:58)

В эту сторону и копаю, но с каждым изменением проблемный код всё больше отделяется от остального, а потенциальные проблемы находить становится всё сложнее. Смущает упоминание на форумах подобных явлений (в т.ч. именно с этими функциями) под названием spurious wakeup:уж больно красивое название, чтобы обоначать ошибку прикладного программиста, а не фичу системы. Хотя доселе ни разу не слышал о таком вообще.



Страницы: 1 вся ветка

Форум: "Прочее";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.46 MB
Время: 0.096 c
15-1339585593
KSergey
2012-06-13 15:06
2013.03.22
Про собеседы-то зачем ветку удалили?!


2-1345811633
Егорка
2012-08-24 16:33
2013.03.22
Безопасен ли вызов в DllMain такой функции


2-1333499708
Dron55555555555
2012-04-04 04:35
2013.03.22
Дробные числа 2


15-1354393802
Юрий
2012-12-02 00:30
2013.03.22
С днем рождения ! 2 декабря 2012 воскресенье


2-1339837887
Разведка
2012-06-16 13:11
2013.03.22
Как происходит уничтожение в структуре класса





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский