Что может блокировать getmodulefilename?
У нас есть многопоточное приложение. Один из рабочих потоков вызывает GetModuleFilename для ведения журнала, и мы видели тупик, когда рабочие потоки удерживали блокировку перед вызовом GetModuleFilename, который блокируется навсегда.
Мы можем и удалили вызов GetModuleFilename изнутри этой блокировки, но все еще очень заинтересованы в том, как именно происходит взаимоблокировка.
Чтение в Интернете: http://blogs.msdn.com/b/oldnewthing/archive/2004/01/28/63880.aspx
похоже, что GetModuleFilename получит блокировку загрузчика, которая казалась довольно хорошим кандидатом в тупик.
Но, как правило, потоки внутри блокировки загрузчика не будут выполнять какой-либо наш собственный код, кроме как в dllmain по ссылке выше.
dll_thread_attach или detach может быть вызван в блокировке загрузчика и на другом рабочем потоке, который создается или уничтожается, но я не вижу способа, которым это попыталось бы получить блокировку, которую мы используем.
Также возможно, что основной поток пытается получить блокировку, которую удерживает поток GetModuleFilename, а третий поток удерживает блокировку загрузчика и выполняет sendmessage или что-то в этом роде в основном потоке? Здесь также я не нашел никаких обстоятельств, при которых это произойдет.
один из других потоков, который я подозреваю, это тот, который использует объект com. В начале поток вызывает coinitialize, поэтому он должен находиться в однопоточной квартире. Есть ли здесь возможности взаимодействия с loaderlock?
В любом случае мы не смогли определить точный путь возникновения этого тупика. Так что я надеюсь на некоторые идеи или дополнительную информацию о блокировке загрузчика с точки зрения других случаев, если она будет получена, и если есть какие-либо другие сценарии, где код будет выполняться в блокировке загрузчика, который потенциально может блокировать.
Благодарю.
2 ответа
Что ж, оказывается, проблема, которую я описал, была просто симптомом другой проблемы в библиотеке, которую мы использовали. Библиотека, очевидно, использовала некоторые API Wininet в двух разных потоках, один из которых был в dllmain и внутри блокировки загрузчика. Эти два потока заблокированы, что впоследствии заблокировало наш поток, который называется GetModuleFileName.
Это примерно столько, сколько я знаю на данный момент, но я обновлю это, как только мы получим более подробную информацию от продавца библиотеки.
Просто несколько случайных идей:
Если есть код C++ (не только C), возможно, что конструкторы статически размещенных объектов в DLL также выполняются, пока система удерживает блокировку загрузки. Разве вы не используете свой замок в конструкторе / деструкторе такого объекта?
Возможно, ошибка может быть там, несмотря на вашу блокировку, и использование блокировки может на самом деле просто "показать" гонку, например, изменив время выполнения действий в каком-либо потоке.
DllMain()
и темы могут быть хитрыми. См. http://blogs.msdn.com/b/oldnewthing/archive/2007/09/04/4731478.aspx