Информация об изменениях

Сообщение Re[6]: [MSVC] Грабли: thread_local могут конструироваться до от 17.03.2017 8:21

Изменено 17.03.2017 8:22 Videoman

Re[6]: [MSVC] Грабли: thread_local могут конструироваться до обычных глобальных
Здравствуйте, Кодт, Вы писали:

К>Не понял сценария зависания. Можешь по шагам расписать?


К>- предисловие-к-main собралось инициализировать статики

К>- залочило глобальный мьютекс
К>- в конструкторе X создали новый поток
К>- — в этом потоке полезли что-то инициализировать (какие-то внутренние статики — например, глобальную таблицу потоков или TLS-ов)
К>- — для этого надо было залочить мьютекс
К>- — опаньки!

К>Так, что ли?


Говорю как в VS2013:
1. В main создали глобальный объект в нем, например, создали поток и запустили.
2. Выходим из main.
3. Рантайм берет глобальный лок и в нем начинает звать деструктуры глобальных объектов через механизм at_exit
4. Дойдя до деструктора глобального объекта с потоком, мы оповещается поток, тем или иным способом о том что нужно завершится и садимся на join ("виснем").
5. Поток получает сигнал и пытается завершиться. Доходит до _endthreadex.
6. _endthreadex, как я понимаю, пытается чистить глобалные объекты потока (thread_local), но перед этим пытается захватить тотже лок, что и at_exit.
7. Результат — дедлок!
Re[6]: [MSVC] Грабли: thread_local могут конструироваться до
Здравствуйте, Кодт, Вы писали:

К>Не понял сценария зависания. Можешь по шагам расписать?


К>- предисловие-к-main собралось инициализировать статики

К>- залочило глобальный мьютекс
К>- в конструкторе X создали новый поток
К>- — в этом потоке полезли что-то инициализировать (какие-то внутренние статики — например, глобальную таблицу потоков или TLS-ов)
К>- — для этого надо было залочить мьютекс
К>- — опаньки!

К>Так, что ли?


Говорю как в VS2013:
1. В main создали глобальный объект. В нем, например, создали поток и запустили.
2. Выходим из main.
3. Рантайм берет глобальный лок и в нем начинает звать деструктуры глобальных объектов через механизм at_exit
4. Дойдя до деструктора глобального объекта с потоком, мы оповещается поток, тем или иным способом о том что нужно завершится и садимся на join ("виснем").
5. Поток получает сигнал и пытается завершиться. Доходит до _endthreadex.
6. _endthreadex, как я понимаю, пытается чистить глобалные объекты потока (thread_local), но перед этим пытается захватить тотже лок, что и at_exit.
7. Результат — дедлок!