Следом за предыдущей, нашел еще одну неприятную ситуацию с thread sanitizer. Но теперь это на 100% ложно позитивное срабатывание.
Посмотреть можно на godbolt: https://godbolt.org/z/zfGfhq89d
Суть в том, что в одной нити захватывается сперва mutex у child-а, а затем, при все еще захваченном mutex-е child-а, захватывается mutex у parent-а.
А потом, когда все ранее захваченные mutex-ы освобождены, уже на другой нити сперва захватывается mutex у parent-а, а следом, не отпуская mutex parent-а, захватывается mutex у child-а.
Thread sanitizer выдает предупреждение о потенциальном дедлоке из-за инверсии порядка захвата мутексов.
Только вот здесь эта инверсия невозможна в принципе, т.к. сперва гарантированно заканчиваются все операции с child-ом, и лишь затем стартует нить, на которой делаются манипуляции с parent-ом.
И вот как удовлетворить thread sanitizer, чтобы он в данном месте не выдавал свою диагностику... Это пока для меня большой вопрос.
Upd. Похоже, это уже известная проблема. С 2022-го года.
|
#include <thread> #include <mutex> struct info { std::mutex m_lock; info * m_parent{ nullptr }; info * m_child{ nullptr }; void activate( info * parent ) { std::lock_guard< std::mutex > lock{ m_lock }; m_parent = parent; m_parent->add_child( this ); } void deactivate() { std::lock_guard< std::mutex > lock{ m_lock }; if( m_child ) m_child->deactivate(); } void add_child( info * child ) { std::lock_guard< std::mutex > lock{ m_lock }; m_child = child; } }; int main() { info parent, child; child.activate( &parent ); std::thread parallel_task{ [&parent] { parent.deactivate(); } }; parallel_task.join(); } |
Комментариев нет:
Отправить комментарий