ThreadSanitizer (tsan) - значимая информация из общей библиотеки

Мое приложение использовало библиотеку 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 в моем каталоге сборки wxWidgets 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 вызывает большую часть моего кода, поэтому я не думаю, что смогу заблокировать любой стек, включая библиотеку. И, конечно, даже если бы я мог создать файл подавления с использованием смещений, если бы я перекомпилировал библиотеку, все это могло бы измениться.

1 ответ

Решение

Проблема в том, что во 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" работают нормально.

Другие вопросы по тегам