boost::thread вызывает небольшую утечку дескриптора события?

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

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 от sysinternal, было обнаружено, что существует проблема утечки дескриптора. Каждые 500 проходов счетчик дескрипторов увеличивается на 1 и никогда не возвращается обратно. Увеличивается дескриптор типа «Событие». Дескрипторы файлов и потоков не увеличиваются (конечно, количество дескрипторов увеличивается по мере создания потоков, но каждые сто проходов выполняется вызов Sleep(10000), чтобы дождаться их очистки, чтобы можно было наблюдать за счетчиком дескрипторов).

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

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

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


person He Shiming    schedule 16.11.2009    source источник
comment
Создание 100 запросов и их немедленная выгрузка обычно занимает около 3 секунд на Intel CoreDuo E6600. И пиковое количество открытых дескрипторов составляет около 300 (включая события, потоки, файлы и другие). Когда тест переходит в спящее состояние, число открытых дескрипторов постепенно снижается примерно до 65. Каждые 500 проходов этого теста приводят к увеличению конечного числа с 65 до 66, а затем до 67. На самом деле это один раз на каждые 50 000 выполнений. Это очень странно и неприятно.   -  person He Shiming    schedule 16.11.2009
comment
количество открытых дескрипторов постепенно уменьшается, потому что их собирает поток монитора очистки.   -  person He Shiming    schedule 16.11.2009


Ответы (1)


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

person Björn Pollex    schedule 16.11.2009
comment
Конечно, он заблокирован с помощью мьютекса. Синхронизация здесь не проблема. Блокировка делается там, где это необходимо. В противном случае, не вызовет ли это утечку дескриптора потока вместо дескриптора события? Странно то, что утечка происходит только с 0,2% запроса. - person He Shiming; 16.11.2009
comment
Я думаю, что утечка в 0,2% гораздо более вероятна, чем любая другая цифра. Участники Boost — талантливые программисты. Простая 100% утечка не пропустит. Гораздо более вероятно, что утечка связана с малозаметным состоянием гонки, которое случается редко. Однако по умолчанию я предполагаю, что boost делает правильную вещь, если вы действительно думаете, что нашли что-то, урежьте это до наименьшего количества кода, который воспроизведет проблему, и попадите в списки рассылки boost. - person deft_code; 16.11.2009