Мое приложение использовало библиотеку wxWidgets, созданную из исходного кода через gcc 5.1.0, с использованием -g и -O0.
Я скомпилировал свое приложение, используя clang ++ 36 -g -fsanitize = thread -stdlib = libc ++, и связал его, используя clang ++ 36 -g -fsanitize = thread -stdlib = libc ++ -lc ++ abi. Он динамически связывается с wxWidgets.
Одно из предупреждений, которое я получил, было:
==================
WARNING: ThreadSanitizer: lock-order-inversion (potential deadlock) (pid=52741)
Cycle in lock order graph: M115 (0x7d080000ea60) => M976 (0x7d0800000100) => M115
Mutex M976 acquired here while holding mutex M115 in main thread:
#0 pthread_mutex_lock /home/xxx/sourceInstallations/llvm-3.6.0/projects/compiler-rt/lib/tsan/../sanitizer_common/sanitizer_common_interceptors.inc:3008 (wxDebugSleep+0x00000043b0ef)
#1 <null> <null> (libwx_baseu-3.0.so.0+0x0000002376fa)
#2 _start <null> (wxDebugSleep+0x00000041be4e)
Hint: use TSAN_OPTIONS=second_deadlock_stack=1 to get more informative warning message
Mutex M115 acquired here while holding mutex M976 in main thread:
#0 pthread_mutex_lock /home/xxx/sourceInstallations/llvm-3.6.0/projects/compiler-rt/lib/tsan/../sanitizer_common/sanitizer_common_interceptors.inc:3008 (wxDebugSleep+0x00000043b0ef)
#1 <null> <null> (libwx_baseu-3.0.so.0+0x0000002376fa)
#2 wxCriticalSectionLocker::wxCriticalSectionLocker(wxCriticalSection&) /usr/local/include/wx-3.0/wx/thread.h:307:9 (wxDebugSleep+0x000000473216)
#3 <null> <null> (libwx_baseu-3.0.so.0+0x00000018b297)
#4 _start <null> (wxDebugSleep+0x00000041be4e)
SUMMARY: ThreadSanitizer: lock-order-inversion (potential deadlock) ??:0 ??
==================
Я не был счастлив, потому что: (1) я хотел бы попытаться найти ошибки потоков в библиотеке wxWidgets; и (2) я бы хотел, чтобы файл подавления работал с одним или рядом с одним отношением предупреждения к файлу подавления.
Итак, я перекомпилировал / связал библиотеку wxWidgets из исходного кода через clang 3.6.0, добавив -fsanitize = thread -stdlib = libc ++ -lc ++ abi. Скрестил пальцы, и все закончилось просто отлично.
Запустил sudo make uninstall в моем каталоге сборки wccWidgets gcc, а sudo установил в моем каталоге сборки wxWidgets clang.
Предупреждение выше теперь показывает:
==================
WARNING: ThreadSanitizer: lock-order-inversion (potential deadlock) (pid=68453)
Cycle in lock order graph: M115 (0x7d080000ea60) => M976 (0x7d0800000100) => M115
Mutex M976 acquired here while holding mutex M115 in main thread:
#0 pthread_mutex_lock /home/xxx/sourceInstallations/llvm-3.6.0/projects/compiler-rt/lib/tsan/../sanitizer_common/sanitizer_common_interceptors.inc:3008 (wxDebugSleep+0x00000043b0ef)
#1 <null> <null> (libwx_baseu-3.0.so.0+0x0000003c24f9)
#2 <null> <null> (libwx_baseu-3.0.so.0+0x0000003d0387)
#3 <null> <null> (libwx_baseu-3.0.so.0+0x0000003d0000)
#4 <null> <null> (libwx_baseu-3.0.so.0+0x0000001bd91c)
#5 <null> <null> (libwx_baseu-3.0.so.0+0x000000279cd6)
#6 <null> <null> (libwx_baseu-3.0.so.0+0x00000027a6da)
#7 <null> <null> (libwx_baseu-3.0.so.0+0x00000024445d)
#8 <null> <null> (libwx_baseu-3.0.so.0+0x000000244243)
#9 <null> <null> (libwx_baseu-3.0.so.0+0x000000245a67)
#10 <null> <null> (libwx_baseu-3.0.so.0+0x000000246856)
#11 <null> <null> (libwx_baseu-3.0.so.0+0x000000245430)
#12 <null> <null> (libwx_baseu-3.0.so.0+0x000000245934)
#13 main /home/xxx/code/testing/wxDebugSleep/wxDebugSleep.cpp:11:1 (wxDebugSleep+0x000000472e9c)
Hint: use TSAN_OPTIONS=second_deadlock_stack=1 to get more informative warning message
Mutex M115 acquired here while holding mutex M976 in main thread:
#0 pthread_mutex_lock /home/xxx/sourceInstallations/llvm-3.6.0/projects/compiler-rt/lib/tsan/../sanitizer_common/sanitizer_common_interceptors.inc:3008 (wxDebugSleep+0x00000043b0ef)
#1 <null> <null> (libwx_baseu-3.0.so.0+0x0000003c24f9)
#2 <null> <null> (libwx_baseu-3.0.so.0+0x0000003d0387)
#3 wxCriticalSection::Enter(void) /usr/local/include/wx-3.0/wx/thread.h:291:52 (wxDebugSleep+0x00000047c570)
#4 wxCriticalSectionLocker::wxCriticalSectionLocker(wxCriticalSection&) /usr/local/include/wx-3.0/wx/thread.h:307:9 (wxDebugSleep+0x000000473216)
#5 <null> <null> (libwx_baseu-3.0.so.0+0x000000245cf0)
#6 <null> <null> (libwx_baseu-3.0.so.0+0x000000246949)
#7 <null> <null> (libwx_baseu-3.0.so.0+0x00000024574b)
#8 <null> <null> (libwx_baseu-3.0.so.0+0x000000245934)
#9 main /home/xxx/code/testing/wxDebugSleep/wxDebugSleep.cpp:11:1 (wxDebugSleep+0x000000472e9c)
SUMMARY: ThreadSanitizer: lock-order-inversion (potential deadlock) ??:0 ??
==================
Я определил TSAN_OPTIONS = second_deadlock_stack = 1 в среде работающей программы, и это не изменило вывод.
Ну, это некоторый прогресс. Я уверен, что я буду использовать неправильный термин, но это как будто отсутствует файл символов для библиотеки.
Я проверил, что он динамически связывается с новой библиотекой с помощью Clang & -fsanitize = thread (ldd и timestamps.)
Я проверил, что библиотека компилируется с -g и -O0 (хотя она может быть и выше).
В случае, если это важно, FreeBSD 10.1 64-bit. Clang составлен из исходного кода.
Вопрос 1 — Как я могу получить «трассировку стека» из общей библиотеки, чтобы показать имя файла и номера строк?
Вопрос 2 — Если я не могу, как я могу сделать хороший файл подавления? Проблема в том, что wxWidgets вызывает большую часть моего кода, поэтому я не думаю, что смогу заблокировать любой стек, включая библиотеку. И, конечно, даже если бы я мог создать файл подавления с использованием смещений, если бы я перекомпилировал библиотеку, все это могло бы измениться.
Проблема в том, что во FreeBSD 10.1 и более ранних версиях есть ошибка, препятствующая корректной работе llvm-symbolizer. llvm-symbolizer — это то, как TSAN получает информацию о символах. Более конкретно, FreeBSD дает имя dlpi_name без пути в dl_iterate_phdr. Это было исправлено в https://reviews.freebsd.org/D932. Патч доступен во FreeBSD 10-STABLE (на данный момент ответ похож на бета-версию 10.2) и должен быть во FreeBSD 10.2 и более поздних версиях.
Кстати, «-Wl, — version-script …» и «-Wl, -soname» работают нормально.