Отладка приложений



              

Требования утилиты DeadlockDetection - часть 3


Операционная система использует эту секцию, чтобы синхронизировать различные действия, которые случаются "за сценой" процесса. Одной из ситуаций, в которых используется критическая секция, является сериализация1выполнения DllMain для следующих четырех случаев ее вызова: DLL_PROCESS_ATTACH (присоединение DLL-процесса), DLL_THREAD_ATTACH (присоединение DLL-потока), DLL_THREAD_ DETACH (отсоединение DLL-потока) и DLL_PROCESS_DETACH (отсоединение DLL-процесса). Причину обращения к DliMain указывает ее второй параметр.

 Сериализация — преобразование в последовательную форму. — Пер.

В приложении, над которым работала команда, запрос к LoadLibrary заставил операционную систему захватить критическую секцию процесса для того, чтобы вызывать DliMain для случая DLL_PROCESS_ATTACH. Затем функция DliMain порождала второй поток. Всякий раз, когда процесс порождает новый поток, операционная система захватывает критическую секцию процесса так, чтобы она могла вызывать функцию DliMain каждой загружаемой DLL для случая DLLJTHREAEKATTACH. В этой конкретной программе второй поток блокировался, потому что критическую секцию процесса содержал первый поток. К сожалению, первый поток затем вызывал функцию WaitForSingleObject, чтобы гарантировать, что второй поток способен должным образом инициализировать некоторые разделяемые объекты. Поскольку второй поток был блокирован на критической секции процесса, удерживаемой первым потоком, а первый поток блокирован при ожидании второго потока, результатом была обычная взаимоблокировка.

Урок

Очевидный урок таков: необходимо избегать любых вызовов ожидающих (Wait*-) функций внутри DliMain. Однако проблемы с критической секцией процесса касаются не только Юа11:*-функций. Операционная система использует критическую секцию процесса и при вызове других фунций (CreateProcess, GetModuleFileName, GetProcAddress, LoadLibrary И FreeLibrary), так ЧТО не нужно вызывать любую из этих функций в DliMain. Поскольку DliMain обзаводится критической секцией процесса, то она может одновременно выполнять только один поток.

Итак, даже опытные разработчики могут допускать многопоточные ошибки—и, как я уже говорил ранее, этот вид ошибок часто происходит в том месте кода, где их меньше всего ожидают.




Содержание  Назад  Вперед