Тонкие блокировки чтения / записи не помнят, кто владельцы есть, так что вам придется найти их другим способом
Raymond | 10 августа 2011 г.
Тонкая блокировка чтения / записи является очень удобным средством синхронизации, но одним из недостатков является то, что он не> отслеживает кем являются текущие владельцы.
Когда ваш поток застревает в ожидании получения тонкой блокировки чтения / записи, естественно знать, каким потокам принадлежит ресурс, которого застрял поток> ждет.
Поскольку нет возможности перейти от ожидающего потока к потокам-владельцам, вам просто нужно найти потоки-владельцы другим способом. Вот поток>, который ожидает блокировки в режиме совместного использования:
ntdll!ZwWaitForKeyedEvent+0xc
ntdll!RtlAcquireSRWLockShared+0x126
dbquery!CSearchSpace::Validate+0x10b
dbquery!CSearchSpace::DecomposeSearchSpace+0x3c
dbquery!CQuery::AddConfigs+0xdc
dbquery!CQuery::ResolveProviders+0x89
dbquery!CResults::CreateProviders+0x85
dbquery!CResults::GetProviders+0x61
dbquery!CResults::CreateResults+0x11c
Хорошо, как найти поток, которому принадлежит блокировка?
Во-первых, тонкие блокировки чтения / записи являются может использоваться только внутри процесса, поэтому потоки-кандидаты - это те, которые находятся внутри процесса.
Во-вторых, шаблон использования для блокировок почти всегда выглядит примерно так:
enter lock
do something
exit lock
Это весьма необычно для функция для взятия блокировки и выхода на внешний код
с удержанной блокировкой. (Он может выходить из другого кода в том же компоненте, передавая обязательство по выходу из блокировки для этого другого кода.)
Поэтому вы хотите искать потоки, которые все еще находятся внутри dbquery.dll
, возможно, даже все еще внутри CSearchSpace
(если блокировка является блокировкой для каждого объекта, а не> глобальной).
Конечно, возможно, что код, введенный в блокировку, испортился и забыл ее снять, но если это так В этом случае никакие поиски> ничего не найдут, поскольку виновник давно ушел.
Поскольку отладка - это упражнение в оптимизме , мы можем также исходить из предположения, что> мы находимся не по делу. Если он не может найти владельца блокировки, возможно, нам придется пересмотреть это предположение.
Наконец, последний трюк - это знать , какие потоки игнорировать .
На данный момент вы также можете игнорировать потоки, ожидающие блокировки, поскольку они являются жертвами, а не причиной. (Опять же, если нам не удается найти владельца блокировки, мы> можем вернуться к предположению, что они не являются причиной; например, они могут пытаться получить блокировку рекурсивно.)
Как это происходит,
есть только один поток в процессе, который проходит все вышеупомянутые фильтры.
dbquery!CProp::Marshall+0x3b
dbquery!CRequest::CRequest+0x24c
dbquery!CQuery::Execute+0x668
dbquery!CResults::FillParams+0x1c4
dbquery!CResults::AddProvider+0x4e
dbquery!CResults::AddConfigs+0x1c5
dbquery!CResults::CreateResults+0x145
Возможно, это не является источником проблемы, но это хорошее начало.
(На самом деле, это выглядит очень многообещающе, поскольку проблема, вероятно,
в том, что процесс на другой стороне маршаллера застрял.)