I have created a class "Client" that is derived from Poco::Net::HTTPClientSession.
Whenever I start a http server on localhost and a Client that connects to it I can reproduce a memoryleak and a coredump if call fast and repeatedly:
"if (!connected()) reconnect();" within the Client class.
If I use:
"if (mustReconnect()) reconnect();" this does not happen.
A run with gdb shows that there must be a problem with the thread implementation - here is the backtrace:
Program received signal SIGINT, Interrupt.
[Switching to Thread -1239491664 (LWP 6168)]
0x009a005b in pthread_sigmask () from /lib/tls/libpthread.so.0
(gdb) bt
#0 0x009a005b in pthread_sigmask () from /lib/tls/libpthread.so.0
#1 0x0808bfb0 in Poco~058~~058~ThreadImpl~058~~058~entry ()
#2 0x0099cdd8 in start_thread () from /lib/tls/libpthread.so.0
#3 0x00e48fca in clone () from /lib/tls/libc.so.6
I am not sure but maybe the fast calling triggers a race condition in the Poco thread implementation ?
Maybe this happens only on this machine? Here is the configuration:
CPU: 4 x Intel(R) Xeon(TM) CPU 3.06GHz
Poco: 1.3.2
$gcc -v
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2.3/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --host=i386-redhat-linux
Thread model: posix
gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-59)
I attach the main.cpp that I used here - if somebody is interested in the rest of the code I can send it on request:
- Code: Select all
#include <sys/types.h>
#include <unistd.h>
#include <iostream>
#include <fstream>
#include <Poco/Exception.h>
#include <Poco/Net/ServerSocket.h>
#include <Poco/Net/HTTPServerParams.h>
#include <Poco/Net/HTTPServer.h>
#include <Poco/NumberFormatter.h>
#include <Poco/URI.h>
#include <Poco/Net/HTTPClientSession.h>
#include <Poco/DateTime.h>
#include <Poco/DateTimeFormatter.h>
#include <Poco/DateTimeFormat.h>
#include "RequestHandlerFactory.hpp"
class Client : public Poco::Net::HTTPClientSession
{
public:
Client(const Poco::URI& p_uri)
: Poco::Net::HTTPClientSession(), m_uri(p_uri)
{
setHost(m_uri.getHost());
setPort(m_uri.getPort());
}
void doSomething()
{
if (!connected()) reconnect();
//if (mustReconnect()) reconnect();
}
~Client()
{
if (connected()) close();
//if (!mustReconnect()) close();
}
private:
Poco::URI m_uri;
};
std::size_t getVmSize()
throw(Poco::Exception)
{
const std::string strProcFile("/proc/" + Poco::NumberFormatter::format(getpid()) + "/status");
std::ifstream inFile(strProcFile.c_str());
if (!inFile)
throw Poco::Exception("Can't open input file '" + strProcFile + "' !");
std::string strKey;
std::size_t intVal(0);
while(inFile.good())
{
inFile >> strKey;
if (inFile.good() && (strKey == "VmSize:"))
{
inFile >> intVal;
break;
}
}
inFile.close();
if (!intVal)
throw Poco::Exception("No VmSize found in file '" + strProcFile + "' !" );
return intVal;
};
int main(void)
{
std::string url( "http://localhost:3330/" );
//std::string url( "http://www.google.at/" );
Poco::URI serverUrl(url);
std::size_t count(0);
std::size_t vmSizeOld(0);
std::size_t vmSizeNew(0);
try
{
while(1)
{
Poco::Net::HTTPServerParams* pParams = new Poco::Net::HTTPServerParams();
Poco::Net::ServerSocket svs(serverUrl.getPort());
RequestHandlerFactory* factory = new RequestHandlerFactory();
Poco::Net::HTTPServer srv(factory, svs, pParams);
srv.start();
Client cs(serverUrl);
cs.doSomething();
srv.stop();
++count;
vmSizeNew = getVmSize();
if (vmSizeOld != vmSizeNew)
{
std::string strDate=Poco::DateTimeFormatter::format(Poco::DateTime(), Poco::DateTimeFormat::ISO8601_FORMAT, 2);
std::cerr << strDate << " VmSize: " << vmSizeNew << " loop " << count << std::endl;
vmSizeOld = vmSizeNew;
}
}
}
catch (const Poco::Exception& ex)
{
std::cerr << ex.displayText() << std::endl;
return 1;
}
catch (...)
{
std::cerr << "ERROR: I N L A S T C A T C H B L O C K !!" << std::endl;
return 1;
}
return 0;
}





