[Asio] async_connect leaking memory/handles ?
Hello there, New to the list and using Boost Asio. I've implemented an SSL connection using async_connect ok, but find that it seems to leave resources allocated when completed and the SSL connection object is destroyed. The application using the Boost SSL functionality creates a socket connection as required then releases it. Its running on a windows platform with Microsoft Visual Studio 2008 and Boost 1.36.0. The problem can be easily illustrated by simple modification of http://www.boost.org/doc/libs/1_36_0/doc/html/boost_asio/example/ssl/cli ent.cpp to place the main functionality in a loop. Then monitoring the process using TaskManager to display Mem Usage and Handles shows both steadily going up. The number of handles increments by 1,2 or 3 on each async_connect. This happens regardless of whether it actually manages to connect or not. A modification to not use SSL has no effect. A further modification to use a synchronous connect and the program then does not bleed resources. Is this a known problem ? Or is there something which I should be releasing myself ? The actual code I tested is shown below. The relevant parts are: 1) main() line 140: while (true) 2) class client() line 32: simple socket connect (resources released ok) 3) class client() line 41: original async_connect (resources not released ok) Any ideas gratefully received ! /Jim // // client.cpp // ~~~~~~~~~~ // // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #include <cstdlib> #include <iostream> #include <boost/bind.hpp> #include <boost/asio.hpp> #include <boost/asio/ssl.hpp> using boost::asio::ip::tcp; enum { max_length = 1024 }; class client { public: client(boost::asio::io_service& io_service, boost::asio::ssl::context& context, boost::asio::ip::tcp::resolver::iterator endpoint_iterator) : simpleSocket_(io_service) ,socket_(io_service, context) { boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator; // This consumes no resources simpleSocket_.connect(endpoint); // This consumes resources // simpleSocket_.async_connect(endpoint, // boost::bind(&client::handle_connect, this, // boost::asio::placeholders::error, // ++endpoint_iterator)); // This original code consumes resources // socket_.lowest_layer().async_connect(endpoint, // boost::bind(&client::handle_connect, this, // boost::asio::placeholders::error, ++endpoint_iterator)); } void handle_connect(const boost::system::error_code& error, boost::asio::ip::tcp::resolver::iterator endpoint_iterator) { std::cout << "handled connect"; return; if (!error) { socket_.async_handshake(boost::asio::ssl::stream_base::client, boost::bind(&client::handle_handshake, this, boost::asio::placeholders::error)); } else if (endpoint_iterator != boost::asio::ip::tcp::resolver::iterator()) { socket_.lowest_layer().close(); boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator; socket_.lowest_layer().async_connect(endpoint, boost::bind(&client::handle_connect, this, boost::asio::placeholders::error, ++endpoint_iterator)); } else { std::cout << "Connect failed: " << error << "\n"; } } void handle_handshake(const boost::system::error_code& error) { if (!error) { std::cout << "Enter message: "; std::cin.getline(request_, max_length); size_t request_length = strlen(request_); boost::asio::async_write(socket_, boost::asio::buffer(request_, request_length), boost::bind(&client::handle_write, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } else { std::cout << "Handshake failed: " << error << "\n"; } } void handle_write(const boost::system::error_code& error, size_t bytes_transferred) { if (!error) { boost::asio::async_read(socket_, boost::asio::buffer(reply_, bytes_transferred), boost::bind(&client::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } else { std::cout << "Write failed: " << error << "\n"; } } void handle_read(const boost::system::error_code& error, size_t bytes_transferred) { if (!error) { std::cout << "Reply: "; std::cout.write(reply_, bytes_transferred); std::cout << "\n"; } else { std::cout << "Read failed: " << error << "\n"; } } private: tcp::socket simpleSocket_; boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_; char request_[max_length]; char reply_[max_length]; }; int main(int argc, char* argv[]) { try { if (argc != 3) { std::cerr << "Usage: client <host> <port>\n"; return 1; } while (true) { std::cout << "Creating service\n"; boost::asio::io_service io_service; boost::asio::ip::tcp::resolver resolver(io_service); boost::asio::ip::tcp::resolver::query query(argv[1], argv[2]); boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); boost::asio::ssl::context ctx(io_service, boost::asio::ssl::context::sslv23); ctx.set_verify_mode(boost::asio::ssl::context::verify_peer); ctx.load_verify_file("ca.pem"); client c(io_service, ctx, iterator); io_service.run(); } } catch (std::exception& e) { std::cerr << "Exception: " << e.what() << "\n"; } return 0; }
Jim Methley <jmeth <at> safetel.no> writes:
I’ve implemented an SSL connection using async_connect ok, but find that it seems to leave resources allocated when completed and the SSL connection object is destroyed.
The application using the Boost SSL functionality creates a socket connection as required then releases it.
Its running on a windows platform with Microsoft Visual Studio 2008 and Boost 1.36.0.
Tested with latest Boost version 1.37.0 and looks like the problem has been fixed. Would have been nice to have seen a mention of bug fixes in the version log, but I'm happy that its fixed :-) /Jim
participants (1)
-
Jim Methley