У меня серьезная проблема с .NET Windows Service. Он работает на нескольких серверах с очень разными конфигурациями. Служба, похоже, подвержена сбоям на некоторых серверах, но стабильна на других. Нестабильность вводится недавно, но пока условия неизвестны. У нас есть серверы под управлением Windows 2003 / Windows 2003 R2 / Windows 2008. Большинство из них полностью обновлены.
Мы пытались создать сервис для разных версий target-framework-версии (2.0 / 3.5 / 4.0), но это не имеет значения. Машины с нестабильным сервисом нестабильны с каждой версией фреймворка. Я пытался восстановить платформы .NET, но это тоже не имеет значения. Насколько я могу судить, весь сервис и его зависимости находятся в управляемом коде.
Я также пытался запустить серверный код в версии для командной строки. Это, кажется, работает стабильно. Мы используем это в качестве обходного пути сейчас. Однако проблема не связана с учетной записью пользователя. Служба обычно работает как «Локальная служба». Я попытался запустить его под локальной учетной записью администратора, которая используется для запуска версии командной строки. Но служба все еще нестабильна.
До сих пор я смог создать воспроизводимую ситуацию на одном из серверов:
- Запустите сервис на сервере.
- Войдите в систему как пользователь домена в новом сеансе RDP на том же сервере.
- Запустите наше клиентское программное обеспечение, которое обращается к нашему сервису через TCP-удаленное взаимодействие в этом сеансе.
- Закройте клиент и сессию.
- Откройте новый сеанс RDP с пользователем домена на сервере.
- Мгновенный сбой в обслуживании!
Обратите внимание, что служба падает в тот момент, когда пользователь домена входит в новый сеанс RDP. На этом этапе наше клиентское программное обеспечение не было запущено. Если я не открою клиент и не получу доступ к службе с помощью удаленного взаимодействия по протоколу TCP в первом сеансе, служба не будет аварийно завершена во время второго входа в систему. Если я открою сеансы как локальный администратор, служба также не выйдет из строя.
Мне удалось подключить встроенный отладчик (OllyDbg) к аварийно завершающему сервису. Сбой с нарушением прав доступа при попытке выполнить по адресу 0x4bcdcee9. Этот адрес одинаков для всех серверов и конфигураций (я видел этот адрес каждый раз в журнале событий). Я посмотрел на стек сбой потока. Кажется, что нить создана непосредственно перед сбоем. Сначала он пытается загрузить Ole32.dll. Он запускает некоторый код из Ole32, а затем я вижу, что эти функции вызываются:
- User32.SetTimer
- User32.GetMessageW
- User32.TranslateMessage
- User32.DispatchMessageW
Сбой находится где-то в DispatchMessageW. Я могу видеть аргумент * MSG для DispatchMessageW в стеке. Похоже, это прошло:
- hWnd = 0x00090082
- Сообщение = 0x0000001e
- wParam = 0x00000000
- lParam = 0x00000000
Я пробовал Spy ++. Но он, похоже, не обнаруживает никаких hWnd в службе Windows.
Итак, служба получает это сообщение, пытается проанализировать и отправить его и каждый раз завершает вызов 0x4bc4cee9, который не отображает память и вылетает.
РЕДАКТИРОВАТЬ: По предложению Ганса я исследовал системные события. Я отлаживал сервис. Я добавил дополнительный сервис к своему исполняемому файлу, чтобы я мог запустить вспомогательный сервис, затем подключить отладчик и запустить реальный сервис. Таким образом, я могу отладить даже запуск службы. Я установил точки останова на SetWindowsHookA, SetWindowsHookW, SetWindowsHookExA и SetWindowsHookExW, но ни одна из них не была достигнута!?
РЕДАКТИРОВАТЬ 2: Я проверил все свои заметки и обнаружил, что я сделал неверные выводы, потому что в моих заметках была опечатка: -S В любом случае адрес сбоя - 0x4bc4cee9.В какой-то момент выполнения msado15.dll загружается туда.Я вижу, что когда клиент отключается от сервера, в отладчике есть 2 управляемых исключения.Вскоре после этого я вижу сообщение WM_Timer, которое обрабатывается диспетчером и вызывает CoFreeUnusedLibraries ().Это приводит к разгрузке msado15.dll.Я открыл msado15.dll в дизассемблере и загрузил символы от Microsoft.DLL является частью компонентов доступа к данным Microsoft (MDAC) 2.8 SP1.Версия 2.82.4795.0, что указывает на то, что это последняя версия, выпущенная в январе 2011 года. Для ADOConnection и ADORecordset имеются функции Advise () и Unadvise ().Advise () вызывает InitAsyncEvents () и вызывает RegisterClassEx ().WndProc, который передается в RegisterClassEx (), является FireEventOnMainThread (), который находится в 0x4bc4cee9!Я вижу функцию там!Что должно произойти, так это то, что при удалении объектов должны вызываться Unadvise () и DestroyAsyncEvents () и UnregisterClassEx ().Но почему-то этого не происходит.DLL выгружается до того, как она может отменить регистрацию классов.Который приводит к сбою на следующем событии.Это может как-то относиться к двум управляемым исключениям.Я буду исследовать дальше.
Stacktrace: http://pastebin.com/dsSjMe4Y
Log: http://pastebin.com/qD2MXvHd
Я был бы очень признателен за некоторые рекомендации в этом вопросе.Например, какой процесс может отправлять это сообщение?И как это возможно, что служба отправляет это совершенно неправильно?Как этого избежать?
Спасибо, Хитклифф