четверг, 16 сентября 2010 г.

MAPI, Exchange и Shutdown

   Недавно столкнулся с интересным случаем, когда при завершении работы системы отображалось окно "Программа завершается... Пожалуйста подождите" со временем переходящее в "Программа не отвечает". Ситуация воспроизводилась не каждый раз, но более-менее стабильно.
   Т.о. цикл историй о "зависаниях" при завершении работы системы продолжается :).


   Используя методику, описанную в [1], было снято два дампа и найден "провинившийся" поток. Им оказался один из рабочих потоков, который находился в режиме ожидания (WaitForMultipleObjects). Т.е. работу свою он сделал и спал, ожидая, когда вновь понадобятся его услуги.

   Возник вопрос - как так получилось, что система именно ему шлет сообщение WM_QUERYENDSESSION (тут дело ясное, что до WM_ENDSESSION дело не доходит)? С помощью spy++ выяснилось, что у этого потока есть окно класса "MsoStdCompMgr" без заголовка. Такое окно могло быть создано только какой-то сторонней библиотекой.

   Расследование продолжилось. В ходе его удалось выяснить, что окно это создает Microsoft Office component (вызов CreateWindow был сделан из недр mso.dll). В этот момент рабочий поток выполнял задачу по вычитыванию адресной книги средствами MAPI.

   И вот что оказалось: после финализации MAPI это окно не уничтожалось (DestroyWindow для него не вызывался), рабочий поток засыпал, цикл выборки сообщений он не крутил. А система, видя, что у этого потока есть окно, посылала ему сообщение WM_QUERYENDSESSION при завершении работы системы. А поток это дело "игнорировал" по причине отсутствия цикла выборки сообщений :). Вот такие пироги.

   Такая ситуация возникает при работе с Exchange address book provider через MAPI, если установлен Outlook 2003/2007 (правда не факт, что с последними заплатками). В качестве Workaround-а можно использовать завершение рабочего потока, после вычитывание адресной книги.

Ссылки
[1] Методика диагностики зависания приложения при shutdown-е

Комментариев нет:

Отправить комментарий