Способы найти условия гонки - PullRequest
17 голосов
/ 28 июня 2010

У меня есть немного кода с условием состязания ... Я знаю, что это условие состязания, потому что оно не происходит последовательно, и, кажется, это происходит чаще на двухъядерных машинах.

Это никогда не происходит, когда я отслеживаю.Хотя есть вероятность, что это тоже может быть тупик.Анализируя этапы завершения журналов, где это происходит и не происходит, я смог точно определить эту ошибку в одной функции.Однако я не знаю, где в рамках функции это происходит.Это не на верхнем уровне.

Добавление операторов журнала или точек останова изменит время, если это условие гонки, и предотвратит это.

Есть ли какая-либо техника, которую я могу использовать, кроме получения анализатора состояния гонки, который позволит мне точно определить, где это происходит?

Это в Visual Studio 9 с C ++ (изнеуправляемый сорт).

Ответы [ 8 ]

6 голосов
/ 15 января 2016

В CLang и gcc 4.8+ включен инструмент под названием ThreadSanitizer .

Вы компилируете свой код, используя флаг -fsanitize=thread

Пример:

$ cat simple_race.cc
#include <pthread.h>
#include <stdio.h>

int Global;

void *Thread1(void *x) {
  Global++;
  return NULL;
}

void *Thread2(void *x) {
  Global--;
  return NULL;
}

int main() {
  pthread_t t[2];
  pthread_create(&t[0], NULL, Thread1, NULL);
  pthread_create(&t[1], NULL, Thread2, NULL);
  pthread_join(t[0], NULL);
  pthread_join(t[1], NULL);
}

А на выходе

$ clang++ simple_race.cc -fsanitize=thread -fPIE -pie -g
$ ./a.out 
==================
WARNING: ThreadSanitizer: data race (pid=26327)
  Write of size 4 at 0x7f89554701d0 by thread T1:
    #0 Thread1(void*) simple_race.cc:8 (exe+0x000000006e66)

  Previous write of size 4 at 0x7f89554701d0 by thread T2:
    #0 Thread2(void*) simple_race.cc:13 (exe+0x000000006ed6)

  Thread T1 (tid=26328, running) created at:
    #0 pthread_create tsan_interceptors.cc:683 (exe+0x00000001108b)
    #1 main simple_race.cc:19 (exe+0x000000006f39)

  Thread T2 (tid=26329, running) created at:
    #0 pthread_create tsan_interceptors.cc:683 (exe+0x00000001108b)
    #1 main simple_race.cc:20 (exe+0x000000006f63)
==================
ThreadSanitizer: reported 1 warnings
5 голосов
/ 28 июня 2010

Положите спит в различных частях вашего кода.Что-то, что является поточно-ориентированным, будет поточно-ориентированным, даже если оно (или асинхронный код) спит даже четные секунды.

2 голосов
/ 29 июня 2010

Итак, метод кувалды для меня был следующим, который требует большого терпения и может в лучшем случае вывести вас на правильный путь. Я использовал это, чтобы выяснить, что происходит с этой конкретной проблемой. Я использую точки трассировки, одну в начале предполагаемой высокоуровневой функции и одну в конце. Переместите точку трассировки вниз. Если добавление точки трассировки в начале функции приводит к тому, что ошибка перестает возникать, перемещайте точку трассировки вниз, пока не сможете снова воспроизвести условие. Идея состоит в том, что точка трассировки не повлияет на синхронизацию, если вы разместите ее после вызова, что в конечном итоге вызовет небезопасный код, но будет, если вы разместите ее раньше. Также обратите внимание на ваше окно вывода. Между какими сообщениями происходит ваша ошибка? Вы также можете использовать точки трассировки, чтобы сузить этот диапазон.

Как только вы сузите свою ошибку до управляемой области кода, вы можете добавить точки останова и взглянуть на то, чем занимаются другие потоки на данный момент.

2 голосов
/ 28 июня 2010

Мне повезло с использованием точек трассировки Visual Studio для нахождения условий гонки.Конечно, это все еще влияет на время, но в тех случаях, когда я его использовал, по крайней мере, этого было недостаточно, чтобы полностью предотвратить возникновение условий гонки.Это казалось менее разрушительным, чем выделенное ведение журнала, по крайней мере.

Кроме этого, попробуйте опубликовать код, позволяющий другим просматривать его.Просто детальное изучение кода не является плохим способом найти условия гонки.

2 голосов
/ 28 июня 2010

Лучший способ отследить это - использовать CHESS в Visual Studio. Это не простой инструмент для использования и, вероятно, потребует постепенного тестирования подразделов вашего приложения. Удачи.

2 голосов
/ 28 июня 2010

Действительно, есть некоторые попытки автоматически найти условия гонки.

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

Я думаю, что это относительно молодая область исследований, поэтому, насколько я знаю, в основном есть теоретические статьи на эту тему. Однако попробуйте поискать по одному из приведенных выше ключевых слов, возможно, вы найдете полезную информацию.

1 голос
/ 28 июня 2010

Это также может быть ресурс, который не защищен, что может объяснить несогласованное поведение (особенно если на одном ядре он работает нормально, а не на двухъядерном). В любом случае проверка кода (как для состояния гонки, так и для не поточно-ориентированного исходного кода) может быть кратчайшим путем к решению.

0 голосов
/ 14 февраля 2013

Вы можете использовать такие инструменты, как Intel Inspector , которые могут проверять определенные типы условий гонки.

...