【发布时间】:2011-11-04 17:54:08
【问题描述】:
我有一个由io_service 构造的ip::udp::socket。只有一个boost::thread 调用io_service::run() 方法,还有一个io_service::work 实例以防止io_service::run() 返回。我的ip::udp::socket 的完成处理程序具有自定义的asio_handler_allocate() 和asio_handler_deallocate() 函数,它们由my::custom_memory_pool 支持。
当我的应用程序退出时,这一系列事件发生在我的关闭线程上:
ip::udp::socket::close()work::~work()io_service::stop()thread::join()my::custom_memory_pool::~custom_memory_pool()ip::udp::socket::~socket()thread::~thread()io_service::~io_service()
在第 8 步中,对io_service::~io_service() 的调用导致...
Program terminated with signal 11, Segmentation fault.
#0 0x00000000005ad93c in my::custom_memory_pool<boost::aligned_storage<512u, -1u> >::deallocate (this=0x36323f8, t=0x7fca97a07880)
at memory.hpp:82
82 reinterpret_cast<pool_node*>(t)->next_ = head_;
(gdb) bt 30
#0 0x00000000005ad93c in my::custom_memory_pool<boost::aligned_storage<512u, -1u> >::deallocate (this=0x36323f8, t=0x7fca97a07880)
at memory.hpp:82
#1 0x00000000005ad40a in asio_handler_deallocate (p=0x7fca97a07880, s=96, h=0x7fffe09d5480) at net.cpp:22
#2 0x0000000000571a07 in boost_asio_handler_alloc_helpers::deallocate<socket_multicast::completion_handler> (p=0x7fca97a07880, s=96, h=...)
at /usr/include/boost/asio/detail/handler_alloc_helpers.hpp:51
#3 0x0000000000558256 in boost::asio::detail::reactive_socket_recvfrom_op<boost::asio::mutable_buffers_1, boost::asio::ip::basic_endpoint<boost::asio::ip::udp>, socket_multicast::completion_handler>::ptr::reset (this=0x7fffe09d54b0)
at /usr/include/boost/asio/detail/reactive_socket_recvfrom_op.hpp:81
#4 0x0000000000558310 in boost::asio::detail::reactive_socket_recvfrom_op<boost::asio::mutable_buffers_1, boost::asio::ip::basic_endpoint<boost::asio::ip::udp>, socket_multicast::completion_handler>::do_complete (owner=0x0, base=0x7fca97a07880)
at /usr/include/boost/asio/detail/reactive_socket_recvfrom_op.hpp:112
#5 0x0000000000426706 in boost::asio::detail::task_io_service_operation::destroy (this=0x7fca97a07880)
at /usr/include/boost/asio/detail/task_io_service_operation.hpp:41
#6 0x000000000042841b in boost::asio::detail::task_io_service::shutdown_service (this=0xd4df30)
at /usr/include/boost/asio/detail/impl/task_io_service.ipp:96
#7 0x0000000000426388 in boost::asio::detail::service_registry::~service_registry (this=0xd4a320, __in_chrg=<value optimized out>)
at /usr/include/boost/asio/detail/impl/service_registry.ipp:43
#8 0x0000000000428e99 in boost::asio::io_service::~io_service (this=0xd49f38, __in_chrg=<value optimized out>)
at /usr/include/boost/asio/impl/io_service.ipp:51
所以io_service::~io_service() 正在尝试将一些内存释放给我在第 5 步中销毁的池。
我无法将my::custom_memory_pool::~custom_memory_pool() 移动到io_service::~io_service() 之后。
我预计在io_service::stop() 和thread::join() 返回后,不会再有asio_handler_deallocate() 调用。显然情况并非如此。在第 3 步中我可以做什么来强制 io_service 将其所有完成事件出列并释放其所有处理程序内存,以及如何阻止直到 io_service 完成这些任务?
【问题讨论】:
-
也许我应该将
work::~work()移动到io_service::stop()之后...也许我没有给io_service完成所有操作的机会。 -
如果你明确地调用停止,那么当你破坏
work是无关紧要的。该工作仅防止 io_service 在没有其他待处理任务时自动停止。 -
asio 文档:
io_service::stop()表示“对 run()、run_one()、poll() 或 poll_one() 的后续调用将立即返回。”work::~work()意味着“io_service 对象的 run() 函数在工作进行时不会退出”这一要求的结束。所以我想得越多,似乎正确的顺序必须是io_service::stop()然后是work::~work(),但是文档并没有明确说明。 -
顺序无关。默认情况下,
run()仅在 io_service 停止或没有工作(work对象或挂起的异步操作)可做时返回。通过添加work对象,它可以防止后一种情况。显式调用 stop 导致 run/run_one/... 函数尽快返回,并进一步调用立即返回。然后调用io_service::reset()将允许重新开始处理。这就是stop不删除处理程序的原因,因为没有办法重新启动。
标签: c++ boost boost-asio