Пикник на обочине или не ходите, дети, в DllMain гулять, а то ноги оторвёт.
Точка входа в DLL, так же как и точка входа в программу, - это очень специальное место. Зона. В Зоне действуют свои правила касательно того, что можно делать, а что делать нельзя. В Зоне можно инициализировать локальные данные DLL, можно создавать критические секции. В Зоне нельзя динамически загружать другие Модули или создавать потоки. Любой Сталкер знает и следует правилам Зоны. Все остальные рано или поздно нарушают правила и расплачиваются за это.
Что делает Зону особенной? Иные утверждают, что во всем виноват Загрузчик. Загрузчик единственный, кто понимает язык зависимостей между модулями. Он говорит с модулями, загружает их и вызывает из точки входа. Но Загрузчик слаб. Он не в силах совладать с Модулями, нарушающими правила Зоны.
Модули коварны и злы. Они стремятся окружить себя другими Модулями, от которых они зависят. Они любят создавать циклические зависимости между собой. Они загружают другие DLL в ответ на DLL_PROCESS_ATTACH и вызывают функции из непроинициализированных Модулей. Модули пытаются замаскировать и приумножить свое коварство. Они прикрываются статусом “Delay-Loaded DLL” и расставляют ловушки в конструкторах и деструкторах статических объектов.
Это люди сделали их такими. Люди нарушили правила Зоны. И теперь они расплачиваются за это каждый раз, когда идут в Зону.
На прошлой неделе произошел очередной несчастный случай. Access Violation прошил насквозь lodctr.exe:

А всё из-за того, что loadperf решил, что ему всё можно и попытался зарегистрировать источник событий для Event Log прямо из DllMain. Этот фокус ему удавался до поры до времени, пока advapi32 не стала “Delay-Loaded” . Как только это произошло, вызов RegisterEventSourceW стал приводить к её загрузке, что поломало граф зависимостей Загрузчика и вылилось в попытку использования неинициализированной критической секции в rpcrt4 до того, как была вызвана точка входа rpcrt4!DllMain.
Кто будет следующей жертвой?
P.S. Сслылка по теме: http://msdn2.microsoft.com/en-us/library/ms682583.aspx
[...] from blog.not-a-kernel-guy.com. Filed under: Программирование, Юмор, [...]
Здравсвуйте, Алексей.
А у MS есть какие-нибудь анализаторы (как с уязвимостями) которые бы отслеживали подобные моменты?
>пока advapi32 не стала “Delay-Loaded”
а почему она такой стала?
Есть, но от них мало пользы. Чтобы от них был толк, нужно сначала разорвать все явные кольцевые зависимости (статически связанные DLL), а затем вручную найти все случаи когда из DllMain явно или опосредованно вызывается LoadLibrary. Только после этого такой инструмент будет полезен, так как с его помощью можно будет отлавливать “нарушителей”.
Потытки разорвать все кольцевые зависимости делаются уже давно. Вернее это не попытки даже, а не слабого размера проекты. Но с наскока это не решается - слишком много кода затрагивается. Ситуация постоянно улучшается, но до идеала еще топать и топать.
Эксперименты с черной магией.
Душещипательно.
Вообще все эти игрища с бубном вокруг Disable/EnableThreadLibraryCalls и проч. в свое время много крови попортили. и seh_translator, который если не путаю ничего иначе чем в DLL_PROCESS_ATTACH не работает.
Не люблю Winapi - слишком много trade-off в нем видимо наделали, теперь все это наружу торчит….
_set_se_translator это совсем другой коленкор. Совать его в DLL не очень разумно. Как по мне так им вообще лучше не пользоваться.
а как жить без него? __finally{} и try… finally{} вместе не живут, вроде бы
Живут, просто в разных функциях. _set_se_translator просто устанавливает фильтр, который будет вызван из самого верхнего (считаем, что стек растет вниз) __try/__except. Никто не мешает обернуть свой поток в __try/__except и воспользоватться там аналогичным фильтром.
Причина по которой не стоит использовать _set_se_translator в DLL - это то, что он устанавливает глобальный фильтр для всех потоков, а DLL , по определению, всему потоками не владеет.
Вернее даже не так. DLL владеет только частью стека потока, т.е. начиная с того момента, как была вызвана функция этой DLL. А _set_se_translator влияет на весь поток.
Я так понимаю, что веселье начинается, когда выгружаешь dll, а в потоке где-то затем произойдет SEHовское исключение?
Ага. Еще могут быть всякие нехорошие эффекты, когда код главного модуля рассчитывает поймать SEH исключение, а тут мы на белом коне ему подсовываем C++ исключение.
Оффтопик.
А вы на какой позиции в MS? Senior или Junior?
Это к тому, что довольно периодично проскакивают сообщения о наборах программистов в Фирму (src — blogs.gotdotnet.ru ). Но после вашего блога, начинаешь сомневаться в проф. пригодности
И какой у вас опыт вообще? CV где-то можно посмотреть?
Не приходите к нам, пожалуйста. У нас всё плохо.
P.S. (c) privet.com
Описанное как-то касается .net кода?
Напрямую - нет, так как .NET все эти тонкости от программиста скрывает.