Re[7]: Lib-ы которым нужен явный init/deinit
От: Pzz Россия https://github.com/alexpevzner
Дата: 27.03.08 12:15
Оценка:
Здравствуйте, remark, Вы писали:

Pzz>>Что именно отлаживать? Поток, подчищающий за другими потоками?


R>Да вообще всё.

R>Вот проходишь отладчиком по функции send(), а ничего на самом деле не отослалось. И когда отошлётся — не понятно.

Ну это относится к многопоточности вообще, а не только к рассматриваемому нами случаю.

Pzz>>Завершение потока можно ждать с помощью WaitFor...(). Совершенно не обязательно устраивать поллинг.


R>Да, сам уже подумал, что если мы инициализировали поток, то получили его хендл. Теперь вспомогательный поток может ждать на этом хендле.


Если мы говорим о библиотеке, то собственно создание пользовательских потоков мы не контроллируем. Но хендл текущего потока всегда можно получить, вот таким примерно образом:

    HANDLE thread_handle;

    DuplicateHandle(
        GetCurrentProcess(),
        GetCurrentThread(),
        GetCurrentProcess(),
        &thread_handle,
        0,
        FALSE,
        DUPLICATE_SAME_ACCESS
    );


Pzz>>Нотификации есть, но хорошо запрятаны. За 10 минут поиска по MSDN'у я не смог их найти


R>Да. Я тоже ничего не нахожу. Вообще глупо — понятно, что эта функциональность есть в Win, но почему она работает только для dll?! Почему нельзя сделать что-то типа RegisterThreadMonitor()? Или на худой конец — at_thread_exit(), что б можно было эмулировать объекты с деструкторами в TLS...


Чтобы жизнь мёдом не казалась

В Висте наконец добавили FlsAlloc(), который аллоцирует fiber local storage с деструктором. Вроде обещают звать эту функцию при завершении как фибера, так и потока.
Re[7]: Lib-ы которым нужен явный init/deinit
От: Sergey Россия  
Дата: 27.03.08 12:31
Оценка: 30 (1)
> Да. Действительно. Я ведь там смотрел. Но куда-то не туда посмотрел, и
> решил, что они всё ещё требуют чтобы thread был как dll под win32.
> Вот статья:
> http://www.codeguru.com/Cpp/misc/misc/threadsprocesses/article.php/c6945__2/
>
> Реализация в libs\thread\src\tss_pe.cpp
>
> То, что работает только со статическим ран-таймом я пока не нашёл.

Это мои личные наблюдения. Авторы библиотеки об этой проблеме видимо не в
курсе. Я не помню, писал я про такую багу в бустогруппы или не писал. Если
не лень — убедитесь, что оно не работает и напишите в comp.lib.boost.devel.

> И это очень многообещающе.


Нифига. Оно реально не работает. CRT ищет эту секцию у себя, а не во всех
принадлежащих процессу модулях. Соответственно, в случае статической
линковки все замечательно, в случае динамической — не работает.

> Там только написано:

> #if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB) &&
> defined(_MSC_VER)
>
> И в статье написано только:
> Environment: Visual C++ 6 and above (may work on earlier versions too),
> for .exe's and DLL's running under Windows 95 and later, including console
> apps.
>
>

Таки смотреть надо в код CRT, мало ли кто чего на кодепроджекте напишет.
Posted via RSDN NNTP Server 2.1 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re: Lib-ы которым нужен явный init/deinit
От: Alex Alexandrov США  
Дата: 27.03.08 21:39
Оценка:
Здравствуйте, eao197, Вы писали:

E>Мне интересно, насколько это распространенная практика для C/C++ библиотек. Буду признателен за перечисление известных вам библиотек, которым требуется явный init/deinit.


У libxml, насколько я помню, тоже такие функции есть. Но она сишная.

Вообще, такие функции в кроссплатформенных библиотеках вещь неплохая. Чтобы была возможность все под контролем держать. Инициализация/деинициализация в конструкторах/деструкторах глобальных переменных — вещь опасная иногда.
It's kind of fun to do the impossible (Walt Disney)
Re[8]: Lib-ы которым нужен явный init/deinit
От: Alex Alexandrov США  
Дата: 28.03.08 19:19
Оценка:
Здравствуйте, Sergey, Вы писали:


>> И это очень многообещающе.


S>Нифига. Оно реально не работает. CRT ищет эту секцию у себя, а не во всех

S>принадлежащих процессу модулях. Соответственно, в случае статической
S>линковки все замечательно, в случае динамической — не работает.

Непонятно. Что значит, "CRT ищет эту секцию у себя"? Ведь тот же механизм используется для вызова конструкторов/деструкторов глобальных объектов? Как же там все это находится?

Кроме того, для того, чтобы нас уведомлять о создании/смерти потока, CRT сама должна получить эти нотификации откуда-то? Т.е. у нее должен быть свой DllMain? Или уведомления придут только в случае другие потоки создаются через _beginthread/_beginthreadex?
It's kind of fun to do the impossible (Walt Disney)
Re[7]: Lib-ы которым нужен явный init/deinit
От: gear nuke  
Дата: 29.03.08 07:17
Оценка:
Здравствуйте, remark, Вы писали:

R>http://www.codeguru.com/Cpp/misc/misc/threadsprocesses/article.php/c6945__2/


По-моему, это не то. Вообще, использование atexit для вызовов дестракторов вроде бы и в MSDN где-то документировано было, и другие примеры встречаются. Но вызывается это при завершении первичного треда, да и то, если оно не аварийное.

Нотификаторы на создание\уничтожение треда (согдасно MSDN) есть только в ядре. Однако, есть и "полудокументированный" механизм — см. DLL_THREAD_DETACH в DllMain. Загрузчик создаёт список загруженных модулей, где хранятся и их точки входа. Здесь можно подумать о разных вариантах: от ручного добавления ldr_data_table_entry, до вполне легального — создания и загрузки прокси-dll.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[8]: Lib-ы которым нужен явный init/deinit
От: remark Россия http://www.1024cores.net/
Дата: 29.03.08 10:35
Оценка:
Здравствуйте, Sergey, Вы писали:

>> Да. Действительно. Я ведь там смотрел. Но куда-то не туда посмотрел, и

>> решил, что они всё ещё требуют чтобы thread был как dll под win32.
>> Вот статья:
>> http://www.codeguru.com/Cpp/misc/misc/threadsprocesses/article.php/c6945__2/
>>
>> Реализация в libs\thread\src\tss_pe.cpp
>>
>> То, что работает только со статическим ран-таймом я пока не нашёл.

S>Это мои личные наблюдения. Авторы библиотеки об этой проблеме видимо не в

S>курсе. Я не помню, писал я про такую багу в бустогруппы или не писал. Если
S>не лень — убедитесь, что оно не работает и напишите в comp.lib.boost.devel.

>> И это очень многообещающе.


S>Нифига. Оно реально не работает. CRT ищет эту секцию у себя, а не во всех

S>принадлежащих процессу модулях. Соответственно, в случае статической
S>линковки все замечательно, в случае динамической — не работает.

Проверил. Их версия у меня не работает только под release, т.к. линкер выкидывает некоторые переменные. А статический или динамический ран-тайм не влияет.

Пофиксил это. Выложил рабочую версию:
http://www.rsdn.ru/forum/message/2895408.1.aspx
Автор: remark
Дата: 29.03.08




1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[9]: Lib-ы которым нужен явный init/deinit
От: remark Россия http://www.1024cores.net/
Дата: 29.03.08 10:37
Оценка:
Здравствуйте, Alex Alexandrov, Вы писали:

AA>Здравствуйте, Sergey, Вы писали:



>>> И это очень многообещающе.


S>>Нифига. Оно реально не работает. CRT ищет эту секцию у себя, а не во всех

S>>принадлежащих процессу модулях. Соответственно, в случае статической
S>>линковки все замечательно, в случае динамической — не работает.

AA>Непонятно. Что значит, "CRT ищет эту секцию у себя"? Ведь тот же механизм используется для вызова конструкторов/деструкторов глобальных объектов? Как же там все это находится?


AA>Кроме того, для того, чтобы нас уведомлять о создании/смерти потока, CRT сама должна получить эти нотификации откуда-то? Т.е. у нее должен быть свой DllMain? Или уведомления придут только в случае другие потоки создаются через _beginthread/_beginthreadex?


Да, статический или динамический рантайм действительно не влияет.
Выложил рабочую версию:
http://www.rsdn.ru/forum/message/2895408.1.aspx
Автор: remark
Дата: 29.03.08




1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[8]: Lib-ы которым нужен явный init/deinit
От: remark Россия http://www.1024cores.net/
Дата: 29.03.08 10:38
Оценка:
Здравствуйте, gear nuke, Вы писали:

GN>Здравствуйте, remark, Вы писали:


R>>http://www.codeguru.com/Cpp/misc/misc/threadsprocesses/article.php/c6945__2/


GN>По-моему, это не то. Вообще, использование atexit для вызовов дестракторов вроде бы и в MSDN где-то документировано было, и другие примеры встречаются. Но вызывается это при завершении первичного треда, да и то, если оно не аварийное.


GN>Нотификаторы на создание\уничтожение треда (согдасно MSDN) есть только в ядре. Однако, есть и "полудокументированный" механизм — см. DLL_THREAD_DETACH в DllMain. Загрузчик создаёт список загруженных модулей, где хранятся и их точки входа. Здесь можно подумать о разных вариантах: от ручного добавления ldr_data_table_entry, до вполне легального — создания и загрузки прокси-dll.


http://www.rsdn.ru/forum/message/2895408.1.aspx
Автор: remark
Дата: 29.03.08



1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: Lib-ы которым нужен явный init/deinit
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 29.03.08 19:28
Оценка:
Здравствуйте, remark, Вы писали:

R>Ну хорошо, допустим функцию инициализации для процесса можно заменить ленивой инициализацией, заплатив дополнительной проверкой на основном пути. Допустим, функцию деинициализации для процесса можно вообще опустить, или зарегистрировать atexit(). Допустим инициализацию для потока можно тоже сделать ленивой. НО КАК БЫТЬ С ДЕИНИЦИАЛИЗАЦИЕЙ ДЛЯ ПОТОКА?


Деинициализировать при выходе, почему бы нет?;)) Сделать булевский флаг...
Ну или разрешить многократную инициализацию и деинициализацию.

R>Как ты предлагаешь делать? Не освобождать ресурсы, связанные с потоком? А если приложение создаёт и рушит по 100 потоков в секунду?


А это вообще диверсия (если речь не идёт про явно специализированные случаи типа эрланга). Используйте пулы тредов.;)
The God is real, unless declared integer.
Re[9]: Lib-ы которым нужен явный init/deinit
От: gear nuke  
Дата: 29.03.08 21:05
Оценка:
Здравствуйте, remark, Вы писали:

R>http://www.rsdn.ru/forum/message/2895408.1.aspx
Автор: remark
Дата: 29.03.08


Ага, не дочитал Хорошее решение, особенно в плане того, что способ как бы для этого и присутствует в ОС. Только вот лучше ли оно документировано... Традиционно TLS используют в протекторах, что бы проверить, не прицеплен ли отладчик...
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[4]: Lib-ы которым нужен явный init/deinit
От: remark Россия http://www.1024cores.net/
Дата: 30.03.08 21:09
Оценка:
Здравствуйте, netch80, Вы писали:

N>Здравствуйте, remark, Вы писали:


R>>Ну хорошо, допустим функцию инициализации для процесса можно заменить ленивой инициализацией, заплатив дополнительной проверкой на основном пути. Допустим, функцию деинициализации для процесса можно вообще опустить, или зарегистрировать atexit(). Допустим инициализацию для потока можно тоже сделать ленивой. НО КАК БЫТЬ С ДЕИНИЦИАЛИЗАЦИЕЙ ДЛЯ ПОТОКА?


N>Деинициализировать при выходе, почему бы нет?) Сделать булевский флаг...



Как отловить момент завершения потока?

Ну хотя сейчас я уже знаю:
http://www.rsdn.ru/forum/message/2895408.1.aspx
Автор: remark
Дата: 29.03.08



N>Ну или разрешить многократную инициализацию и деинициализацию.



Если я правильно понял, то речь не об этом. Речь о том, как инициализировать/деинициализировать ресурсы, выделенные для конкретного потока, а не глобальные.


R>>Как ты предлагаешь делать? Не освобождать ресурсы, связанные с потоком? А если приложение создаёт и рушит по 100 потоков в секунду?


N>А это вообще диверсия (если речь не идёт про явно специализированные случаи типа эрланга). Используйте пулы тредов.



Т.е. предлагаешь не инженерное решение, а организационное — автор библиотеки должен постоянно обходить всех клиентов и говорить "Используйте пулы тредов. Пожалуйста."



1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[5]: Lib-ы которым нужен явный init/deinit
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 31.03.08 06:38
Оценка:
Здравствуйте, remark, Вы писали:

R>>>Ну хорошо, допустим функцию инициализации для процесса можно заменить ленивой инициализацией, заплатив дополнительной проверкой на основном пути. Допустим, функцию деинициализации для процесса можно вообще опустить, или зарегистрировать atexit(). Допустим инициализацию для потока можно тоже сделать ленивой. НО КАК БЫТЬ С ДЕИНИЦИАЛИЗАЦИЕЙ ДЛЯ ПОТОКА?

N>>Деинициализировать при выходе, почему бы нет?;)) Сделать булевский флаг...
R>Как отловить момент завершения потока?

R>Ну хотя сейчас я уже знаю:

R>http://www.rsdn.ru/forum/message/2895408.1.aspx
Автор: remark
Дата: 29.03.08


Как завершается тред? Если форсированным убийством без права пискнуть, то всё плохо по-любому. Если обычным путём, управляемым средой языка (return или исключение), то достаточно объекта со счётчиком и логикой "init/deinit только на переходах счётчика между 0 и 1", устанавливаемого в тред в стиле RAII.

N>>Ну или разрешить многократную инициализацию и деинициализацию.


R>Если я правильно понял, то речь не об этом. Речь о том, как инициализировать/деинициализировать ресурсы, выделенные для конкретного потока, а не глобальные.


О выполнении init/deinit в контексте именно данного треда, насколько я понимаю, заботится библиотека.

R>>>Как ты предлагаешь делать? Не освобождать ресурсы, связанные с потоком? А если приложение создаёт и рушит по 100 потоков в секунду?

N>>А это вообще диверсия (если речь не идёт про явно специализированные случаи типа эрланга). Используйте пулы тредов.;)
R>Т.е. предлагаешь не инженерное решение, а организационное — автор библиотеки должен постоянно обходить всех клиентов и говорить "Используйте пулы тредов. Пожалуйста." :)))

Ему как раз пофиг. Не пофиг — автору конечной программы.
The God is real, unless declared integer.
Re[6]: Lib-ы которым нужен явный init/deinit
От: remark Россия http://www.1024cores.net/
Дата: 31.03.08 09:57
Оценка:
Здравствуйте, netch80, Вы писали:

N>Здравствуйте, remark, Вы писали:


R>>>>Ну хорошо, допустим функцию инициализации для процесса можно заменить ленивой инициализацией, заплатив дополнительной проверкой на основном пути. Допустим, функцию деинициализации для процесса можно вообще опустить, или зарегистрировать atexit(). Допустим инициализацию для потока можно тоже сделать ленивой. НО КАК БЫТЬ С ДЕИНИЦИАЛИЗАЦИЕЙ ДЛЯ ПОТОКА?

N>>>Деинициализировать при выходе, почему бы нет?) Сделать булевский флаг...
R>>Как отловить момент завершения потока?

R>>Ну хотя сейчас я уже знаю:

R>>http://www.rsdn.ru/forum/message/2895408.1.aspx
Автор: remark
Дата: 29.03.08


N>Как завершается тред? Если форсированным убийством без права пискнуть, то всё плохо по-любому. Если обычным путём, управляемым средой языка (return или исключение), то достаточно объекта со счётчиком и логикой "init/deinit только на переходах счётчика между 0 и 1", устанавливаемого в тред в стиле RAII.



Тогда я не понял твоего тезиса... Ты с чем-то несогласен? Или что-то предлагаешь?
Можешь пояснить?


N>>>Ну или разрешить многократную инициализацию и деинициализацию.


R>>Если я правильно понял, то речь не об этом. Речь о том, как инициализировать/деинициализировать ресурсы, выделенные для конкретного потока, а не глобальные.


N>О выполнении init/deinit в контексте именно данного треда, насколько я понимаю, заботится библиотека.



О библиотеке как раз и идёт речь. Т.е. ответы типа "а библиотека как-то там это сама сделает" не катят


R>>>>Как ты предлагаешь делать? Не освобождать ресурсы, связанные с потоком? А если приложение создаёт и рушит по 100 потоков в секунду?

N>>>А это вообще диверсия (если речь не идёт про явно специализированные случаи типа эрланга). Используйте пулы тредов.
R>>Т.е. предлагаешь не инженерное решение, а организационное — автор библиотеки должен постоянно обходить всех клиентов и говорить "Используйте пулы тредов. Пожалуйста."

N>Ему как раз пофиг. Не пофиг — автору конечной программы.



Т.е. ты считаешь нормальным, если документация по Windows или Linux содержала бы фразы типа "Вы не должны создавать более 100 потоков в секунду", "Вы не должны делать более 1000 аллокаций памяти в секунду", "Вы не должны выделать блоки памяти более 10 Мб" ("... потому что мы там кое-чо не доделали, поэтому у Вас может кое-где сбоить") ?!



1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[7]: Lib-ы которым нужен явный init/deinit
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 31.03.08 10:08
Оценка:
Здравствуйте, remark, Вы писали:

R>>>Ну хотя сейчас я уже знаю:

R>>>http://www.rsdn.ru/forum/message/2895408.1.aspx
Автор: remark
Дата: 29.03.08

N>>Как завершается тред? Если форсированным убийством без права пискнуть, то всё плохо по-любому. Если обычным путём, управляемым средой языка (return или исключение), то достаточно объекта со счётчиком и логикой "init/deinit только на переходах счётчика между 0 и 1", устанавливаемого в тред в стиле RAII.
R>Тогда я не понял твоего тезиса... Ты с чем-то несогласен? Или что-то предлагаешь? :xz:
R>Можешь пояснить?

Я говорю, что мне кажется, что проблемы тут по сути нет и не было.

N>>>>Ну или разрешить многократную инициализацию и деинициализацию.

R>>>Если я правильно понял, то речь не об этом. Речь о том, как инициализировать/деинициализировать ресурсы, выделенные для конкретного потока, а не глобальные.
N>>О выполнении init/deinit в контексте именно данного треда, насколько я понимаю, заботится библиотека.
R>О библиотеке как раз и идёт речь. Т.е. ответы типа "а библиотека как-то там это сама сделает" не катят :)))

Ну?

N>>Ему как раз пофиг. Не пофиг — автору конечной программы.

R>Т.е. ты считаешь нормальным, если документация по Windows или Linux содержала бы фразы типа "Вы не должны создавать более 100 потоков в секунду", "Вы не должны делать более 1000 аллокаций памяти в секунду", "Вы не должны выделать блоки памяти более 10 Мб" ("... потому что мы там кое-чо не доделали, поэтому у Вас может кое-где сбоить") ?! :xz:

Мне не хочется отвечать на непонятно откуда почему возникшие додумки типа "мы там кое-чо не доделали", извини уж. Хочешь фантазировать в пространство — пожалуйста, но я в этом не участник.
The God is real, unless declared integer.
Re[8]: Lib-ы которым нужен явный init/deinit
От: remark Россия http://www.1024cores.net/
Дата: 31.03.08 10:32
Оценка:
Здравствуйте, netch80, Вы писали:

N>Здравствуйте, remark, Вы писали:


R>>>>Ну хотя сейчас я уже знаю:

R>>>>http://www.rsdn.ru/forum/message/2895408.1.aspx
Автор: remark
Дата: 29.03.08

N>>>Как завершается тред? Если форсированным убийством без права пискнуть, то всё плохо по-любому. Если обычным путём, управляемым средой языка (return или исключение), то достаточно объекта со счётчиком и логикой "init/deinit только на переходах счётчика между 0 и 1", устанавливаемого в тред в стиле RAII.
R>>Тогда я не понял твоего тезиса... Ты с чем-то несогласен? Или что-то предлагаешь?
R>>Можешь пояснить?

N>Я говорю, что мне кажется, что проблемы тут по сути нет и не было.



Если обязать пользователя вызывать global_init()/global_deinit()/thread_init()/thread_deinit(), то, да, всё замечательно. И мне лично такое решение очень нравится.
Но дискуссия пошла в русло, что типа ручная инициализация/деинициализация — сакс, и библиотека должна эти вещи сама у себя внутри как-то разруливать.
Если ты за ручную инициализацию/деинициализацию, то тебе наверное лучше ответить не мне, а сюда:
http://www.rsdn.ru/forum/message/2888124.1.aspx
Автор: uzhas
Дата: 24.03.08




1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[9]: Lib-ы которым нужен явный init/deinit
От: Sergey Россия  
Дата: 31.03.08 11:19
Оценка:
> S>Нифига. Оно реально не работает. CRT ищет эту секцию у себя, а не во
> всех
> S>принадлежащих процессу модулях. Соответственно, в случае статической
> S>линковки все замечательно, в случае динамической — не работает.
>
> Проверил. Их версия у меня не работает только под release, т.к. линкер
> выкидывает некоторые переменные. А статический или динамический ран-тайм
> не влияет.

Очень странно, что работает, потому что я этим вопросом заинересовался
именно в контексте "а почему не чистятся boost::thread_specific_ptr, если
boost::thread прилинковать статически; вроде ж обещали что теперь работает".
Конфигурация у меня была чуть сложнее, чем простой exe — наличествовали
несколько dll, поторые статически линковались с boost::thread.

> Пофиксил это. Выложил рабочую версию:

> http://www.rsdn.ru/forum/message/2895408.1.aspx
Автор: remark
Дата: 29.03.08


Действительно работает. Разница с бустом, насколько я понимаю — наличие
static __declspec(thread) int volatile use_tls;
В бусте (1.34.1) "__declspec(thread)" мне удалось обнаружить единственный
раз, в комментах. Так же не используется #pragma comment(linker,
"/INCLUDE:__tls_used")

Видимо, желающим линковать статически boost::thread и не иметь при этом
проблем с разрушением tss можно посоветовать вставлять в код #pragma
comment(linker, "/INCLUDE:__tls_used")

Самое смешное, что без __declspec(thread) или __tls_used не заработал даже
вариант со статически прилинкованным рантаймом (компилятор правда под рукой
оказался только от VC2008).

Что интересно — нотификация DLL_THREAD_ATTACH похоже присылается без участия
CRT:
A.exe!on_tls_callback(HINSTANCE__ * __formal=0x002d0000, unsigned long
dwReason=0x00000002, HINSTANCE__ * __formal=0x002d0000) Line 41 C++
ntdll.dll!_LdrpCallInitRoutine@16() + 0x14 bytes
ntdll.dll!_LdrpCallTlsInitializers@8() + 0x5d1ee bytes
ntdll.dll!_LdrpInitializeThread@4() — 0x304b5 bytes
ntdll.dll!__LdrpInitialize@8() + 0x7c bytes
ntdll.dll!_LdrInitializeThunk@8() + 0x10 bytes


Стек при завершении нитки тоже забавный:
> A.exe!on_tls_callback(HINSTANCE__ * __formal=0x002d0000, unsigned long
> dwReason=0x00000003, HINSTANCE__ * __formal=0x002d0000) Line 41 C++
ntdll.dll!_LdrpCallInitRoutine@16() + 0x14 bytes
ntdll.dll!_LdrpCallTlsInitializers@8() + 0x5d1ee bytes
ntdll.dll!_LdrShutdownThread@0() — 0x602da bytes
ntdll.dll!_RtlExitUserThread@4() + 0x2a bytes
A.exe!_endthreadex(unsigned int retcode=0x00000000) Line 414 C
A.exe!_callthreadstartex() Line 348 + 0x15 bytes C
A.exe!_threadstartex(void * ptd=0x00164848) Line 331 C
kernel32.dll!@BaseThreadInitThunk@12() + 0x12 bytes
ntdll.dll!__RtlUserThreadStart@8() + 0x27 bytes

Замена _beginthreadex на CreateThread показала, что on_tls_callback все
равно вызывается, а значит CRT в вызове колбэков участвует только косвенно —
помогая форировать необходимые структуры. О чем, собственно и написано в
комментах в tlssup.c:

/* Start section for TLS callback array examined by the OS loader code.
* If dynamic TLS initialization is used, then a pointer to __dyn_tls_init
* will be placed in .CRT$XLC by inclusion of tlsdyn.obj. This will cause
* the .CRT$XD? array of individual TLS variable initialization callbacks
* to be walked.
*/

_CRTALLOC(".CRT$XLA") PIMAGE_TLS_CALLBACK __xl_a = 0;


Ключевой момент:

_CRTALLOC(".rdata$T")
const IMAGE_TLS_DIRECTORY _tls_used =
{
(ULONG)(ULONG_PTR) &_tls_start, // start of tls data
(ULONG)(ULONG_PTR) &_tls_end, // end of tls data
(ULONG)(ULONG_PTR) &_tls_index, // address of tls_index
(ULONG)(ULONG_PTR) (&__xl_a+1), // pointer to call back array
(ULONG) 0, // size of tls zero fill
(ULONG) 0 // characteristics
};
Posted via RSDN NNTP Server 2.1 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.