Как обнаружить круговые звонки? - PullRequest
2 голосов
/ 02 сентября 2011

Я искал причины для взаимоблокировок и стратегии / инструменты, чтобы их избежать и обнаружить.

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

Иногда это трудно обнаружить, особенно в очень крупных проектах.

Итак, есть ли какие-либо инструменты / библиотеки / методы, позволяющие автоматизировать обнаружение циклических вызовов впрограмма?

РЕДАКТИРОВАТЬ: Я кодирую в основном на C и C ++, поэтому, если возможно, дать любую информацию по теме, которая применима к этим языкам.

Тем не менее, кажется, что эта тема почти не освещена в SO, поэтому ответы на другие языки тоже в порядке. хотя, возможно, те заслуживают отдельной темы, если кто-то сочтет ее актуальной

Спасибо.

Ответы [ 5 ]

1 голос
/ 02 сентября 2011

Если вы используете Linux, есть 2 инструмента Valgrind для обнаружения взаимоблокировок и условий гонки: Helgrind , DRD .Они оба дополняют друг друга, и стоит проверить оба потока на наличие ошибок.

1 голос
/ 02 сентября 2011

Циклические (или рекурсивные) вызовы, которые пытаются получить одну и ту же не входящую блокировку, являются одним из самых простых для отладки сценариев блокировки: блокировка является детерминированной и может быть легко проверена.Когда приложение блокируется, запустите отладчик и посмотрите на трассировку стека, чтобы понять, какие блокировки удерживаются и почему.

Что касается общих решений проблемы блокировки ... вы можете взглянуть на некоторые библиотеки, которые предоставляютпорядок мьютекса и обнаружение, когда вы пытаетесь заблокировать мьютекс из строя.Решения такого типа могут быть сложными для правильной реализации, но, будучи на месте, они гарантируют, что вы не сможете войти в состояние взаимоблокировки, поскольку вынуждает все процессы получать блокировки в одном и том же порядке (т. Е. Если процесс A удерживает блокировку La и пытаетсячтобы получить блокировку Lb, для которой порядок правильный, тогда он может либо успешно завершиться, либо заблокировать, но какой бы процесс ни удерживал блокировку, Lb не может попытаться заблокировать La, так как ограничение порядка не будет выполнено).

0 голосов
/ 02 сентября 2011

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

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

Существуют стратегии предотвращения тупиков, связанные с назначением приоритетов блокировки и упорядочением блокировок в соответствии с приоритетом. Это требует изменения кода и обеспечения соблюдения стандартов.

0 голосов
/ 02 сентября 2011

Лучший способ обнаружить взаимные блокировки (IMO) - создать тестовую программу, которая вызывает все функции в случайном порядке примерно в 30 различных потоках 10000 раз.

Если вы зашли в тупик, вы можете использовать окно «Параллельные стеки» VS2010. Отладка-> Windows-> Параллельные стеки
Это окно покажет вам все стеки, чтобы вы могли найти методы, которые являются взаимоблокирующими.

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

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

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

Пример:

class Blah {
  MyData data;
  Lock lock;
public:
  DataItem GetData(int index)
  { 
     ReadLock read(lock);
     return LocalGetData(index);
  }
  DataItem FindData(string key)
  {
     ReadLock read(lock);
     DataItem item;
     //find the item, can use LocalGetData() to get the item without deadlocking
     return item;

  }
  void PutData(DataItem item)
  {
    ReadLock write(lock); 
    //put item in database
  }

private:

  DataItem LocalGetData(int index)
  {
    return data[index];
  }
} 
0 голосов
/ 02 сентября 2011

В Linux вы можете использовать valgrind для обнаружения взаимоблокировок , используйте --tool=helgrind.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...