GDB_DBG Telegram 268
Есть в libc такая функция dl_iterate_phdr. Она позволяет проитерироваться по всем загруженным so-шкам и на каждой выполнить колбэк, который ей передается в качестве параметра. Удобная, классная штука!

А вот как вы думаете, что будет, если из таких вот колбэков позвать dlopen: функцию, которая загружает новые so-шки. Т.е. в момент итерации по коллекции сошек добавить туда новые элементы? Понятно, что идея звучит не блестяще, но все-таки: что именно случится? Сегфолт? UB? Зависнет? Какое-нибудь красивое поведение, типа "вернуть на очередной итерации специальное значение, которое обозначает, что коллекция изменилась"? (ага, щас прям, размечтался, ты не в Java)

Вполне допускаю, что может и сегфолтнуться, но вчера отлаживал прекрасный дедлок, который был вызван вот таким кодом. Прекрасно в нем то, дедлокнулся такой код со случайным тредом-доходягой.

Вот представьте, живет и работает себе тред №1, никак с вашим кодом не связанный. В какой-то момент решает помереть, позвав pthread_exit. Но вот pthread_exit во время своей работы может попытаться подгрузить библиотечку libgcc_s.so (нашел время!), конечно же через dlopen => dlopen в свою очередь первым делом захватит лок на загрузку: dl_load_lock => а потом, если мы реально смогли загрузить библиотеку, попытаемся добавить результат в список загруженных сошек, мы возьмем еще один лок: dl_load_write_lock.

А в этот момент тред №2 такой классный шарится по всем сошкам через dl_iterate_phdr и зовет для каждого из них ваш кастомный колбэк. Конечно же, чтобы пробегать по списку он сначала берет dl_load_write_lock, иначе вдруг список поменяется? А наш кастомный колбэк зовет dlopen, который, как мы уже знаем, первым делом возьмет dl_load_lock. Дедлок!

Понятно, что пример можно было бы намного проще написать: любой другой тред, который пойдет звать dlopen – наш конкурент. Но от бедных тредов-доходяг я такого не ожидал. А случалось все это на терминации рантайма, где как раз все и умирают (очень интересное состояние рантайма).

Да, кстати, в мане для dl_iterate_phdr никто не пишет, что из колбэков не стоит звать dlopen. Но так ведь и над каждой розеткой не пишут, что не стоит в нее пальцы совать.



Смешно, что раньше в нашей кодовой базе на вызове dl_iterate_phdr висела кое-что подсказывающая компилятору пометка @Quick. Потом ее убрали, и проблема начала проявляться. Вопрос веры, получается: пока верили, что вызов быстрый, он и заканчивался быстро, без всяких дедлоков. Стоило усомниться, и вот мы здесь.

#дух_машины
👍13👾8🙈3



tgoop.com/gdb_dbg/268
Create:
Last Update:

Есть в libc такая функция dl_iterate_phdr. Она позволяет проитерироваться по всем загруженным so-шкам и на каждой выполнить колбэк, который ей передается в качестве параметра. Удобная, классная штука!

А вот как вы думаете, что будет, если из таких вот колбэков позвать dlopen: функцию, которая загружает новые so-шки. Т.е. в момент итерации по коллекции сошек добавить туда новые элементы? Понятно, что идея звучит не блестяще, но все-таки: что именно случится? Сегфолт? UB? Зависнет? Какое-нибудь красивое поведение, типа "вернуть на очередной итерации специальное значение, которое обозначает, что коллекция изменилась"? (ага, щас прям, размечтался, ты не в Java)

Вполне допускаю, что может и сегфолтнуться, но вчера отлаживал прекрасный дедлок, который был вызван вот таким кодом. Прекрасно в нем то, дедлокнулся такой код со случайным тредом-доходягой.

Вот представьте, живет и работает себе тред №1, никак с вашим кодом не связанный. В какой-то момент решает помереть, позвав pthread_exit. Но вот pthread_exit во время своей работы может попытаться подгрузить библиотечку libgcc_s.so (нашел время!), конечно же через dlopen => dlopen в свою очередь первым делом захватит лок на загрузку: dl_load_lock => а потом, если мы реально смогли загрузить библиотеку, попытаемся добавить результат в список загруженных сошек, мы возьмем еще один лок: dl_load_write_lock.

А в этот момент тред №2 такой классный шарится по всем сошкам через dl_iterate_phdr и зовет для каждого из них ваш кастомный колбэк. Конечно же, чтобы пробегать по списку он сначала берет dl_load_write_lock, иначе вдруг список поменяется? А наш кастомный колбэк зовет dlopen, который, как мы уже знаем, первым делом возьмет dl_load_lock. Дедлок!

Понятно, что пример можно было бы намного проще написать: любой другой тред, который пойдет звать dlopen – наш конкурент. Но от бедных тредов-доходяг я такого не ожидал. А случалось все это на терминации рантайма, где как раз все и умирают (очень интересное состояние рантайма).

Да, кстати, в мане для dl_iterate_phdr никто не пишет, что из колбэков не стоит звать dlopen. Но так ведь и над каждой розеткой не пишут, что не стоит в нее пальцы совать.



Смешно, что раньше в нашей кодовой базе на вызове dl_iterate_phdr висела кое-что подсказывающая компилятору пометка @Quick. Потом ее убрали, и проблема начала проявляться. Вопрос веры, получается: пока верили, что вызов быстрый, он и заканчивался быстро, без всяких дедлоков. Стоило усомниться, и вот мы здесь.

#дух_машины

BY Алло, это отладочная?


Share with your friend now:
tgoop.com/gdb_dbg/268

View MORE
Open in Telegram


Telegram News

Date: |

In 2018, Telegram’s audience reached 200 million people, with 500,000 new users joining the messenger every day. It was launched for iOS on 14 August 2013 and Android on 20 October 2013. Deputy District Judge Peter Hui sentenced computer technician Ng Man-ho on Thursday, a month after the 27-year-old, who ran a Telegram group called SUCK Channel, was found guilty of seven charges of conspiring to incite others to commit illegal acts during the 2019 extradition bill protests and subsequent months. SUCK Channel Telegram Image: Telegram. Find your optimal posting schedule and stick to it. The peak posting times include 8 am, 6 pm, and 8 pm on social media. Try to publish serious stuff in the morning and leave less demanding content later in the day.
from us


Telegram Алло, это отладочная?
FROM American