2009-11-16 1 views
1

Я отлаживаю этот проект базы данных. Он обеспечивает доступ к SQLite для приложения более высокого уровня. Он предназначен для работы асинхронно, то есть имеет такие методы, как ExecuteRequestAsync() и IsRequestReady(). Когда вызывается ExecuteRequestAsync, он запускает boost :: thread для выполнения задания и немедленно возвращает функцию. Когда приложение более высокого уровня решает, что он больше не хочет получить результат выполнения запроса, он может вызвать DumpRequest(), чтобы отменить его. Так как трудно изящно отменить запрос базы данных, реализация DumpRequest просто поддерживает «поток монитора очистки», который ждет «завершенных запросов» и удаляет их. Все повышение :: темы управляются через буст :: shared_ptr, как:boost :: thread, вызывающий утечку дескриптора небольшого события?

boost::shared_ptr<boost::thread> my_thread = new boost::thread(boost::bind(&DBCon::RunRequest, &this_dbcon)); 

И когда он больше не нужен (не будет отменена):

vector<boost::shared_ptr<boost::thread> > threads_tobe_removed; 
// some iteration 
threads_tobe_removed[i].get()->join(); 
threads_tobe_removed.erase(threads_tobe_removed.begin()+i); 

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

Однако, наблюдая за проектом тестирования модуля через Process Explorer, он обнаружил, что проблема с утечкой ручек. Каждый 500-й ход проходит, количество рукоятки увеличивается на 1 и никогда не возвращается назад. Это тип «Тип события», который увеличивается. Файловые и поточные ручки не увеличиваются (конечно, количество ручек увеличивается с ростом потоков, но есть вызов «Сон» (10000) каждые сотни проходов, чтобы дождаться их очистки, чтобы можно было наблюдать количество обработчиков).

Я не управлял событиями. Они создаются boost :: thread при создании потока. Я только гарантирую, чтобы изящно закрыть потоки, я понятия не имею, для чего используются события.

Мне интересно, есть ли у кого-либо подобные проблемы? Что может быть причиной этой утечки? Является ли этот номер в Process Explorer достаточно надежным, чтобы назвать его утечкой дескриптора? Есть ли способ отслеживать и исправлять его?

Я использую статически связанный boost 1.40 в Windows Vista с Visual C++.

+0

Нерест 100 запросов и их сброс, как правило, занимает около 3 секунд на Intel CoreDuo E6600. Максимальное количество открытых дескрипторов составляет около 300 (включая событие, поток, файлы и т. Д.). Когда тест входит в состояние сна, число открытых ручек постепенно уменьшается примерно до 65. Каждый 500-й ход этого числа приведет к увеличению числа «конец» с 65 до 66, а затем 67. Это на самом деле один раз каждые 50 000 исполнений. Это очень странно и неприятно. –

+0

«число открытых ручек постепенно уменьшается», потому что поток монитора очистки собирает их. –

ответ

1

Доступ к threads_tobe_removed поточно-безопасный? Если нет, может быть состояние гонки, когда один поток добавляет поток в вектор по вызову DumpRequest, в то время как поток монитора очистки удаляет поток из вектора. Таким образом, boost::thread -объекты могут быть уничтожены без присоединения потока сначала, что приведет к тому, что поток будет работать без связанного объекта, что может объяснить утечку.

+0

Конечно, он заблокирован с помощью мьютекса. Синхронизация здесь не проблема. Блокировка выполняется там, где это необходимо. В противном случае, не вызовет ли утечка потока потока вместо дескриптора события? Странно, что утечка происходит только с 0,2% запроса. –

+2

Я думаю, что утечка 0,2% гораздо более вероятна, чем любое другое число. Boost contributors - талантливые кодеры. Не пропустите простую 100-процентную утечку.Гораздо более вероятно, что утечка происходит из состояния тонкой гонки, которое редко случается. Однако по умолчанию я полагаю, что boost делает все правильно, если вы действительно думаете, что нашли что-то, разделив его на наименьший объем кода, который воспроизведет проблему и ударит списки рассылки. –