Я использую автономную библиотеку Asio для размещения простого TCP-сервера.Код находится внутри динамической библиотеки, которая загружается хост-приложением, которое я не могу контролировать.
Библиотека предоставляет функции Open
и Close
, которые хост-приложение должно вызывать после загрузки /перед выгрузкой библиотеки.
В функции Open
я запускаю asio::io_service
в отдельном потоке:
// start accepting connections
server.accept();
// start the asio service in a new thread
serviceThread = std::make_unique<std::thread>([this]() {
ioService.run();
});
В функции Close
я останавливаю службу и присоединяюсь к потоку:
// stop the asio service
ioService.stop();
serviceThread->join();
Серверная функция accept
реализована следующим образом:
void Server::accept() {
acceptor.async_accept(socket, [this](std::error_code err) {
if (!err) {
std::lock_guard<std::mutex> lock(sessionsMutex);
sessions.emplace_back(new Session(*this, ioService, std::move(socket)));
}
accept();
});
}
Другие функции, вызываемые asio::io_service
, реализованы аналогично, то есть привязка лямбда-функции this
передается в функцию asio async
.
Этот код прекрасно работает, когда хост-приложение вызывает Open
и Close
, как требуется.
Однако иногда хост-приложение не вызываетфункция Close
перед выгрузкой библиотеки, приводящая к ошибке сегментации, вызванной неправильным чтением памяти:
Thread 14 Crashed:
0 com. 0x0000000121f1b14b asio::detail::scheduler::post_immediate_completion(asio::detail::scheduler_operation*, bool) + 27 (scheduler.ipp:281)
1 com. 0x0000000121f1f17c void asio::io_context::executor_type::post<asio::detail::work_dispatcher<myproject::Server::Session::write()::$_3>, std::__1::allocator<void> >(asio::detail::work_dispatcher<myproject::Server::Session::write()::$_3>&&, std::__1::allocator<void> const&) const + 124 (io_context.hpp:270)
2 com. 0x0000000121f1f027 asio::async_result<std::__1::decay<myproject::Server::Session::write()::$_3>::type, void ()>::return_type asio::post<asio::io_context::executor_type, myproject::Server::Session::write()::$_3>(asio::io_context::executor_type const&, myproject::Server::Session::write()::$_3&&, std::__1::enable_if<is_executor<asio::io_context::executor_type>::value, void>::type*) + 87 (post.hpp:58)
3 com. 0x0000000121f11cb2 asio::async_result<std::__1::decay<myproject::Server::Session::write()::$_3>::type, void ()>::return_type asio::post<asio::io_context, myproject::Server::Session::write()::$_3>(asio::io_context&, myproject::Server::Session::write()::$_3&&, std::__1::enable_if<is_convertible<asio::io_context&, asio::execution_context&>::value, void>::type*) + 50 (post.hpp:69)
[...]
Какие у меня варианты?Существует ли кросс-платформенный способ обнаружения выгрузки библиотеки (должен работать в macOS и Windows), который позволяет мне в любом случае выполнить очистку?
Могу ли я изменить использование Asio для решения этой проблемы?поведение?