Я отлаживаю этот проект базы данных. Он обертывает доступ к 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++.