Overview
Features
Download
Documentation
Community
Add-Ons & Services

Memoryleak and coredump in HTTPClientSession ?

Please post support and help requests here.

Memoryleak and coredump in HTTPClientSession ?

Postby quirxi123 » 05 Jun 2008, 09:12

Hello,

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;
}

quirxi123
 
Posts: 6
Joined: 21 Apr 2008, 10:00

Re: Memoryleak and coredump in HTTPClientSession ?

Postby guenter » 05 Jun 2008, 11:30

Two things beforehand:
- you are not supposed to create a subclass of HTTPClientSession
- also, you are not supposed to call reconnect() yourself (there's a reason it's protected).

Now, if you absolutely convinced that you must create a subclass of HTTPClientSession and call reconnect() yourself, please send the full code to the mailing list, so that we can look at the issue (the forum, unfortunately, sucks for sourcecode viewing).

guenter
 
Posts: 1135
Joined: 11 Jul 2006, 16:27
Location: Austria

Re: Re: Memoryleak and coredump in HTTPClientSession ?

Postby alex » 05 Jun 2008, 11:54

> (the forum, unfortunately, sucks for sourcecode viewing).

I have edited the original entry. Code should be enclosed in ~np~
Code: Select all
 
~/np~ tags. In regular text (not necessary in code blocks), double colons can be replaced by ~np~~058~~058~~/np~ for proper formatting.
alex
 
Posts: 1130
Joined: 11 Jul 2006, 16:27
Location: United_States

Re: Re: Memoryleak and coredump in HTTPClientSession ?

Postby quirxi123 » 05 Jun 2008, 12:18

Hello Guenter,

> Two things beforehand: - you are not supposed to create a subclass of HTTPClientSession -

The problem is, that we try to implement a client for the XML-RPC protocol.
Since this protocol entirely runs over http and the client only has to some conversion and verification of the xml-structures prior to sending it to a http-server in my opinion it *is* a HTTPClientSession. If it were not deriven from HTTPClientSession I would have to reimplement all the functionality of a HTTPClientSession like: setPort, setProxy, setProxyHost, setProxyPort, setReconnect etc.
What is the problem with deriving from HTTPClientSession ? I could not find any hint in the documentation. Maybe I miss some point here? If yes, I would be glad if you could correct me!

> also, you are not supposed to call reconnect() yourself (there's a reason it's protected).

Hmm, I always thought that methods are made protected so that they *can* be accessed from derived class? Othewise I would use the "private" keyword ...

>Now, if you absolutely convinced that you must create a subclass of HTTPClientSession and call reconnect() yourself,
> please send the full code to the mailing list, so that we can look at the issue (the forum, unfortunately, sucks for sourcecode viewing).

Yes, thanks for formatting the code. I tried with tags - but it did not work ....

regards,
Arno
quirxi123
 
Posts: 6
Joined: 21 Apr 2008, 10:00

Re: Re: Re: Memoryleak and coredump in HTTPClientSession ?

Postby quirxi123 » 05 Jun 2008, 12:22

> > (the forum, unfortunately, sucks for sourcecode viewing).
>
> I have edited the original entry. Code should be enclosed in ~np~
Code: Select all
 
~/np~ tags. In regular text (not necessary in code blocks), double colons can be replaced by ~np~~058~~058~~/np~ for proper formatting.

I really seem to have problems with this kind of wiki: Is there also a way of force line-breaks ?
quirxi123
 
Posts: 6
Joined: 21 Apr 2008, 10:00

Re: Re: Re: Re: Memoryleak and coredump in HTTPClientSession ?

Postby alex » 05 Jun 2008, 13:38

> I really seem to have problems with this kind of wiki: Is there also a way of force line-breaks ?

Check the documentation.
alex
 
Posts: 1130
Joined: 11 Jul 2006, 16:27
Location: United_States

Re: Re: Re: Memoryleak and coredump in HTTPClientSession ?

Postby guenter » 06 Jun 2008, 22:12

I haven't had the time yet to look on why your code is failing, but, as I said, subclassing HTTPClientSession is not a good idea, unless you're implementing something like a HTTPSClientSession (see NetSSL). As a general rule of thumb, if you use inheritance just because it saves you writing a few forwarding functions, inheritance is very probably misused. A very good guideline when to use inheritance is the Liskov Substitution Principle (see http://en.wikipedia.org/wiki/Liskov_substitution_principle).

In your case, I would either make the HTTPClientSession a private member of your XMLRPC protocol object (at the expense of having to write a few forwarding functions), or provide a constructor that allows you to pass a HTTPClientSession reference to your XMLRPC object (and maintain a pointer or reference ot a HTTPClientSession in your object). This also makes it very easy to replace the HTTPClientSession with a HTTPSClientSession, should you ever need HTTPS in your application.

Furthermore, there should be no need to call reconnect() yourself in your code. This should be handled transparently by HTTPClientSession, which should reuse an existing connection if persistent connections are enabled (and the server has not closed the connection), or create a new one otherwise.
guenter
 
Posts: 1135
Joined: 11 Jul 2006, 16:27
Location: Austria


Return to Support

Who is online

Users browsing this forum: No registered users and 3 guests

cron