|
Boost Users : |
Subject: [Boost-users] [Asio] async_connect leaking memory/handles ?
From: Jim Methley (jmeth_at_[hidden])
Date: 2008-12-08 10:28:02
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;
}
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net