diff --git a/include/boost/asio/detail/dev_poll_reactor.hpp b/include/boost/asio/detail/dev_poll_reactor.hpp index db6f3d1b..17f57d52 100644 --- a/include/boost/asio/detail/dev_poll_reactor.hpp +++ b/include/boost/asio/detail/dev_poll_reactor.hpp @@ -102,15 +102,21 @@ public: BOOST_ASIO_DECL void cancel_ops(socket_type descriptor, per_descriptor_data&); // Cancel any operations that are running against the descriptor and remove - // its registration from the reactor. + // its registration from the reactor. The reactor resources associated with + // the descriptor must be released by calling cleanup_descriptor_data. BOOST_ASIO_DECL void deregister_descriptor(socket_type descriptor, per_descriptor_data&, bool closing); - // Cancel any operations that are running against the descriptor and remove - // its registration from the reactor. + // Remove the descriptor's registration from the reactor. The reactor + // resources associated with the descriptor must be released by calling + // cleanup_descriptor_data. BOOST_ASIO_DECL void deregister_internal_descriptor( socket_type descriptor, per_descriptor_data&); + // Perform any post-deregistration cleanup tasks associated with the + // descriptor data. + BOOST_ASIO_DECL void cleanup_descriptor_data(per_descriptor_data&); + // Add a new timer queue to the reactor. template void add_timer_queue(timer_queue& queue); diff --git a/include/boost/asio/detail/epoll_reactor.hpp b/include/boost/asio/detail/epoll_reactor.hpp index 64c5b270..66ae10db 100644 --- a/include/boost/asio/detail/epoll_reactor.hpp +++ b/include/boost/asio/detail/epoll_reactor.hpp @@ -123,14 +123,22 @@ public: per_descriptor_data& descriptor_data); // Cancel any operations that are running against the descriptor and remove - // its registration from the reactor. + // its registration from the reactor. The reactor resources associated with + // the descriptor must be released by calling cleanup_descriptor_data. BOOST_ASIO_DECL void deregister_descriptor(socket_type descriptor, per_descriptor_data& descriptor_data, bool closing); - // Remote the descriptor's registration from the reactor. + // Remove the descriptor's registration from the reactor. The reactor + // resources associated with the descriptor must be released by calling + // cleanup_descriptor_data. BOOST_ASIO_DECL void deregister_internal_descriptor( socket_type descriptor, per_descriptor_data& descriptor_data); + // Perform any post-deregistration cleanup tasks associated with the + // descriptor data. + BOOST_ASIO_DECL void cleanup_descriptor_data( + per_descriptor_data& descriptor_data); + // Add a new timer queue to the reactor. template void add_timer_queue(timer_queue& timer_queue); diff --git a/include/boost/asio/detail/impl/dev_poll_reactor.ipp b/include/boost/asio/detail/impl/dev_poll_reactor.ipp index efe2ba70..7efb05ed 100644 --- a/include/boost/asio/detail/impl/dev_poll_reactor.ipp +++ b/include/boost/asio/detail/impl/dev_poll_reactor.ipp @@ -235,6 +235,11 @@ void dev_poll_reactor::deregister_internal_descriptor( op_queue_[i].cancel_operations(descriptor, ops, ec); } +void dev_poll_reactor::cleanup_descriptor_data( + dev_poll_reactor::per_descriptor_data&) +{ +} + void dev_poll_reactor::run(bool block, op_queue& ops) { boost::asio::detail::mutex::scoped_lock lock(mutex_); diff --git a/include/boost/asio/detail/impl/epoll_reactor.ipp b/include/boost/asio/detail/impl/epoll_reactor.ipp index 610ce31c..f7fbce0a 100644 --- a/include/boost/asio/detail/impl/epoll_reactor.ipp +++ b/include/boost/asio/detail/impl/epoll_reactor.ipp @@ -359,9 +359,6 @@ void epoll_reactor::deregister_descriptor(socket_type descriptor, descriptor_lock.unlock(); - free_descriptor_state(descriptor_data); - descriptor_data = 0; - io_service_.post_deferred_completions(ops); } } @@ -387,7 +384,14 @@ void epoll_reactor::deregister_internal_descriptor(socket_type descriptor, descriptor_data->shutdown_ = true; descriptor_lock.unlock(); + } +} +void epoll_reactor::cleanup_descriptor_data( + per_descriptor_data& descriptor_data) +{ + if (descriptor_data) + { free_descriptor_state(descriptor_data); descriptor_data = 0; } diff --git a/include/boost/asio/detail/impl/kqueue_reactor.ipp b/include/boost/asio/detail/impl/kqueue_reactor.ipp index b4a7a10b..4172294d 100644 --- a/include/boost/asio/detail/impl/kqueue_reactor.ipp +++ b/include/boost/asio/detail/impl/kqueue_reactor.ipp @@ -312,9 +312,6 @@ void kqueue_reactor::deregister_descriptor(socket_type descriptor, descriptor_lock.unlock(); - free_descriptor_state(descriptor_data); - descriptor_data = 0; - io_service_.post_deferred_completions(ops); } } @@ -344,7 +341,14 @@ void kqueue_reactor::deregister_internal_descriptor(socket_type descriptor, descriptor_data->shutdown_ = true; descriptor_lock.unlock(); + } +} +void kqueue_reactor::cleanup_descriptor_data( + per_descriptor_data& descriptor_data) +{ + if (descriptor_data) + { free_descriptor_state(descriptor_data); descriptor_data = 0; } diff --git a/include/boost/asio/detail/impl/reactive_descriptor_service.ipp b/include/boost/asio/detail/impl/reactive_descriptor_service.ipp index 56caec9f..a0300c47 100644 --- a/include/boost/asio/detail/impl/reactive_descriptor_service.ipp +++ b/include/boost/asio/detail/impl/reactive_descriptor_service.ipp @@ -88,10 +88,12 @@ void reactive_descriptor_service::destroy( reactor_.deregister_descriptor(impl.descriptor_, impl.reactor_data_, (impl.state_ & descriptor_ops::possible_dup) == 0); - } - boost::system::error_code ignored_ec; - descriptor_ops::close(impl.descriptor_, impl.state_, ignored_ec); + boost::system::error_code ignored_ec; + descriptor_ops::close(impl.descriptor_, impl.state_, ignored_ec); + + reactor_.cleanup_descriptor_data(impl.reactor_data_); + } } boost::system::error_code reactive_descriptor_service::assign( @@ -128,9 +130,15 @@ boost::system::error_code reactive_descriptor_service::close( reactor_.deregister_descriptor(impl.descriptor_, impl.reactor_data_, (impl.state_ & descriptor_ops::possible_dup) == 0); - } - descriptor_ops::close(impl.descriptor_, impl.state_, ec); + descriptor_ops::close(impl.descriptor_, impl.state_, ec); + + reactor_.cleanup_descriptor_data(impl.reactor_data_); + } + else + { + ec = boost::system::error_code(); + } // The descriptor is closed by the OS even if close() returns an error. // @@ -154,6 +162,7 @@ reactive_descriptor_service::release( BOOST_ASIO_HANDLER_OPERATION(("descriptor", &impl, "release")); reactor_.deregister_descriptor(impl.descriptor_, impl.reactor_data_, false); + reactor_.cleanup_descriptor_data(impl.reactor_data_); construct(impl); } diff --git a/include/boost/asio/detail/impl/reactive_socket_service_base.ipp b/include/boost/asio/detail/impl/reactive_socket_service_base.ipp index 3b677e47..3594ae05 100644 --- a/include/boost/asio/detail/impl/reactive_socket_service_base.ipp +++ b/include/boost/asio/detail/impl/reactive_socket_service_base.ipp @@ -89,6 +89,8 @@ void reactive_socket_service_base::destroy( boost::system::error_code ignored_ec; socket_ops::close(impl.socket_, impl.state_, true, ignored_ec); + + reactor_.cleanup_descriptor_data(impl.reactor_data_); } } @@ -102,9 +104,15 @@ boost::system::error_code reactive_socket_service_base::close( reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, (impl.state_ & socket_ops::possible_dup) == 0); - } - socket_ops::close(impl.socket_, impl.state_, false, ec); + socket_ops::close(impl.socket_, impl.state_, false, ec); + + reactor_.cleanup_descriptor_data(impl.reactor_data_); + } + else + { + ec = boost::system::error_code(); + } // The descriptor is closed by the OS even if close() returns an error. // diff --git a/include/boost/asio/detail/impl/select_reactor.ipp b/include/boost/asio/detail/impl/select_reactor.ipp index 80686eaf..869f7349 100644 --- a/include/boost/asio/detail/impl/select_reactor.ipp +++ b/include/boost/asio/detail/impl/select_reactor.ipp @@ -163,6 +163,11 @@ void select_reactor::deregister_internal_descriptor( op_queue_[i].cancel_operations(descriptor, ops); } +void select_reactor::cleanup_descriptor_data( + select_reactor::per_descriptor_data&) +{ +} + void select_reactor::run(bool block, op_queue& ops) { boost::asio::detail::mutex::scoped_lock lock(mutex_); diff --git a/include/boost/asio/detail/impl/signal_set_service.ipp b/include/boost/asio/detail/impl/signal_set_service.ipp index 56313e09..a1f43de4 100644 --- a/include/boost/asio/detail/impl/signal_set_service.ipp +++ b/include/boost/asio/detail/impl/signal_set_service.ipp @@ -187,6 +187,7 @@ void signal_set_service::fork_service( state->fork_prepared_ = true; lock.unlock(); reactor_.deregister_internal_descriptor(read_descriptor, reactor_data_); + reactor_.cleanup_descriptor_data(reactor_data_); } break; case boost::asio::io_service::fork_parent: @@ -541,6 +542,7 @@ void signal_set_service::remove_service(signal_set_service* service) lock.unlock(); service->reactor_.deregister_descriptor( read_descriptor, service->reactor_data_, false); + service->reactor_.cleanup_descriptor_data(service->reactor_data_); lock.lock(); #endif // !defined(BOOST_ASIO_WINDOWS) // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) diff --git a/include/boost/asio/detail/impl/win_iocp_socket_service_base.ipp b/include/boost/asio/detail/impl/win_iocp_socket_service_base.ipp index 22818f7e..93f5ed07 100644 --- a/include/boost/asio/detail/impl/win_iocp_socket_service_base.ipp +++ b/include/boost/asio/detail/impl/win_iocp_socket_service_base.ipp @@ -177,9 +177,16 @@ boost::system::error_code win_iocp_socket_service_base::close( reinterpret_cast(&reactor_), 0, 0)); if (r) r->deregister_descriptor(impl.socket_, impl.reactor_data_, true); - } - socket_ops::close(impl.socket_, impl.state_, false, ec); + socket_ops::close(impl.socket_, impl.state_, false, ec); + + if (r) + r->cleanup_descriptor_data(impl.reactor_data_); + } + else + { + ec = boost::system::error_code(); + } impl.socket_ = invalid_socket; impl.state_ = 0; @@ -629,10 +636,14 @@ void win_iocp_socket_service_base::close_for_destruction( reinterpret_cast(&reactor_), 0, 0)); if (r) r->deregister_descriptor(impl.socket_, impl.reactor_data_, true); + + boost::system::error_code ignored_ec; + socket_ops::close(impl.socket_, impl.state_, true, ignored_ec); + + if (r) + r->cleanup_descriptor_data(impl.reactor_data_); } - boost::system::error_code ignored_ec; - socket_ops::close(impl.socket_, impl.state_, true, ignored_ec); impl.socket_ = invalid_socket; impl.state_ = 0; impl.cancel_token_.reset(); diff --git a/include/boost/asio/detail/kqueue_reactor.hpp b/include/boost/asio/detail/kqueue_reactor.hpp index 6aba2b26..c6182b4d 100644 --- a/include/boost/asio/detail/kqueue_reactor.hpp +++ b/include/boost/asio/detail/kqueue_reactor.hpp @@ -125,14 +125,22 @@ public: per_descriptor_data& descriptor_data); // Cancel any operations that are running against the descriptor and remove - // its registration from the reactor. + // its registration from the reactor. The reactor resources associated with + // the descriptor must be released by calling cleanup_descriptor_data. BOOST_ASIO_DECL void deregister_descriptor(socket_type descriptor, per_descriptor_data& descriptor_data, bool closing); - // Remote the descriptor's registration from the reactor. + // Remove the descriptor's registration from the reactor. The reactor + // resources associated with the descriptor must be released by calling + // cleanup_descriptor_data. BOOST_ASIO_DECL void deregister_internal_descriptor( socket_type descriptor, per_descriptor_data& descriptor_data); + // Perform any post-deregistration cleanup tasks associated with the + // descriptor data. + BOOST_ASIO_DECL void cleanup_descriptor_data( + per_descriptor_data& descriptor_data); + // Add a new timer queue to the reactor. template void add_timer_queue(timer_queue& queue); diff --git a/include/boost/asio/detail/select_reactor.hpp b/include/boost/asio/detail/select_reactor.hpp index 69b04c82..d6f75242 100644 --- a/include/boost/asio/detail/select_reactor.hpp +++ b/include/boost/asio/detail/select_reactor.hpp @@ -107,13 +107,20 @@ public: BOOST_ASIO_DECL void cancel_ops(socket_type descriptor, per_descriptor_data&); // Cancel any operations that are running against the descriptor and remove - // its registration from the reactor. + // its registration from the reactor. The reactor resources associated with + // the descriptor must be released by calling cleanup_descriptor_data. BOOST_ASIO_DECL void deregister_descriptor(socket_type descriptor, per_descriptor_data&, bool closing); - // Remote the descriptor's registration from the reactor. + // Remove the descriptor's registration from the reactor. The reactor + // resources associated with the descriptor must be released by calling + // cleanup_descriptor_data. BOOST_ASIO_DECL void deregister_internal_descriptor( - socket_type descriptor, per_descriptor_data& descriptor_data); + socket_type descriptor, per_descriptor_data&); + + // Perform any post-deregistration cleanup tasks associated with the + // descriptor data. + BOOST_ASIO_DECL void cleanup_descriptor_data(per_descriptor_data&); // Move descriptor registration from one descriptor_data object to another. BOOST_ASIO_DECL void move_descriptor(socket_type descriptor,