Обсуждение: libpq++ memory problems

Поиск
Список
Период
Сортировка

libpq++ memory problems

От
Tim Brookes
Дата:
I have written the following small piece of code to illustrate my
problem.

#include <pgsql/libpq++.h>

void callproc(){  PgDatabase* loStatsdb;  PgEnv loEnv("","","","","");
  loStatsdb = new PgDatabase(loEnv,"ftldb");  delete loStatsdb;
};

main(){  while(1){     callproc();  };
};

The procedure 'callproc' is called in a continuous loop to emphasise
this problem.  Within the procedure all that happens is a new database
connection is made and deleted.  On my system this eats memory at an
enormous rate.

I do not know if this problem has been discussed before or fixed in
newer versions of the library (my apologies if it has), but I would be
most grateful of any info on resolving this memory leak.

Tim Brookes



Re: libpq++ memory problems

От
Tom Lane
Дата:
Tim Brookes <tim.brookes@mcmail.com> writes:
> The procedure 'callproc' is called in a continuous loop to emphasise
> this problem.  Within the procedure all that happens is a new database
> connection is made and deleted.  On my system this eats memory at an
> enormous rate.

I could not reproduce such a leak with current sources.

It appears that you are using a fairly old Postgres release --- class
PgEnv hasn't existed since at least release 6.4.*, maybe earlier.
I'd suggest upgrading...
        regards, tom lane


Re: libpq++ memory problems

От
Tim Brookes
Дата:
OK

So I have downloaded and set up version 6.5.3 on a test system.  I then
altered the code on the example so that it no longer uses the PgEnv class.
I set my environment variable and ran the program now as below.  I still get
a huge memory leak.

Can I ask you what version you are using?

callproc(){  PgDatabase* loStatsdb;
  loStatsdb = new PgDatabase("");  delete loStatsdb;
};

main(){   while(1){       callproc();   };
};

Rgds
Tim Brookes


Tom Lane wrote:

> Tim Brookes <tim.brookes@mcmail.com> writes:
> > The procedure 'callproc' is called in a continuous loop to emphasise
> > this problem.  Within the procedure all that happens is a new database
> > connection is made and deleted.  On my system this eats memory at an
> > enormous rate.
>
> I could not reproduce such a leak with current sources.
>
> It appears that you are using a fairly old Postgres release --- class
> PgEnv hasn't existed since at least release 6.4.*, maybe earlier.
> I'd suggest upgrading...
>
>                         regards, tom lane



Re: libpq++ memory problems

От
Tom Lane
Дата:
Tim Brookes <tim.brookes@mcmail.com> writes:
> So I have downloaded and set up version 6.5.3 on a test system.  I then
> altered the code on the example so that it no longer uses the PgEnv class.
> I set my environment variable and ran the program now as below.  I still get
> a huge memory leak.

> Can I ask you what version you are using?

Current CVS sources --- ie, 7.0RC1 plus or minus a little bit.  But as
far as I can tell from the CVS logs, not much has been done to libpq++
since 6.5; there's certainly nothing in the logs about fixing memory
leaks.  So I'd have expected 6.5 to behave the same.  Interesting.

> callproc(){
>    PgDatabase* loStatsdb;

>    loStatsdb = new PgDatabase("");
>    delete loStatsdb;
> };

> main(){
>     while(1){
>         callproc();
>     };
> };

AFAIR, my test program looked just like that except it specified a
database name --- new PgDatabase("dbname=regression") or some such.

I wonder if it could be platform- or configuration-specific.  What
options did you give to configure?
        regards, tom lane


Re: libpq++ memory problems

От
Tim Brookes
Дата:
Tom

I did not use configure - I downloaded a set of RPMs for 6.5.3
I then just changed the program not to require PgEnv and then compiled,linked with
the libpq++ library.

Maybe I should download the sources and compile on my system, but I dont see how
that will change what I see as momory not being released in the PgDatabase
destructor.

Rgds
Tim

Tom Lane wrote:

> Tim Brookes <tim.brookes@mcmail.com> writes:
> > So I have downloaded and set up version 6.5.3 on a test system.  I then
> > altered the code on the example so that it no longer uses the PgEnv class.
> > I set my environment variable and ran the program now as below.  I still get
> > a huge memory leak.
>
> > Can I ask you what version you are using?
>
> Current CVS sources --- ie, 7.0RC1 plus or minus a little bit.  But as
> far as I can tell from the CVS logs, not much has been done to libpq++
> since 6.5; there's certainly nothing in the logs about fixing memory
> leaks.  So I'd have expected 6.5 to behave the same.  Interesting.
>
> > callproc(){
> >    PgDatabase* loStatsdb;
>
> >    loStatsdb = new PgDatabase("");
> >    delete loStatsdb;
> > };
>
> > main(){
> >     while(1){
> >         callproc();
> >     };
> > };
>
> AFAIR, my test program looked just like that except it specified a
> database name --- new PgDatabase("dbname=regression") or some such.
>
> I wonder if it could be platform- or configuration-specific.  What
> options did you give to configure?
>
>                         regards, tom lane



Re: libpq++ memory problems

От
Lamar Owen
Дата:
Tim Brookes wrote:
> 
> Tom
> 
> I did not use configure - I downloaded a set of RPMs for 6.5.3
> I then just changed the program not to require PgEnv and then compiled,linked with
> the libpq++ library.

To answer Tom's question:

> > I wonder if it could be platform- or configuration-specific.  What
> > options did you give to configure?

To which I can answer, if it was my RPMset he downloaded:
CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=/usr \--enable-hba --enable-locale \--with-perl
--with-mb=SQL_ASCII\--with-tcl--with-tk --with-x \--with-odbc --with-java \--with-python
 

--
Lamar Owen
WGCR Internet Radio
1 Peter 4:11


libpq++ tracing considered harmful (was Re: libpq++ memory problems)

От
Tom Lane
Дата:
Ah-hah, figured it out.  There *was* a recent relevant change, but the
log message for it didn't say anything about leaks.  The problem is
in the "debug" code for PgConnection, which in 6.5.* looks like:

// PgConnection::connect
// establish a connection to a backend
ConnStatusType PgConnection::Connect(const char* conninfo)
{
ConnStatusType cst; // Turn the trace on
#if defined(DEBUG) FILE *debug = fopen("/tmp/trace.out","w"); PQtrace(pgConn, debug);
#endif  // Connect to the database pgConn = PQconnectdb(conninfo);

This is busted in at least five ways:

1. "DEBUG" is a symbol defined in the backend header files (it's a  severity level constant for elog()).  So although
libpq++'sMakefile  thinks it can turn the code on or off via -DDEBUG, it's mistaken;  that debug-tracing code always
getscompiled.  Oliver Elphick fixed that a month or so ago by changing the  controlling symbol to "DEBUGFILE".  So
that'swhy you see the leak  in 6.5.3 and I don't see it in current sources.
 

2. The fopen'd file is never closed.  (The destructor calls PQuntrace  but that routine isn't responsible for closing
thefile.)  That's  the direct cause of the memory and file descriptor leak you see:  a stdio file is fopen'd and never
fclose'dfor each PgConnection  created.
 

3. The whole thing is a complete waste of time because the pgConn  object doesn't exist yet --- it's not created till
thenext line!  So PQtrace is being handed either a null pgConn pointer (which I  believe it will silently ignore) or a
garbagepointer (which could  have who-knows-what unpleasant consequences).  But in no case will  any tracing actually
occur. Sheesh.
 

4. If any tracing did occur, all of the output from (perhaps many)  different PgConnection objects in different program
runswould all  get dumped into the same temp file, leaving it of doubtful use to  anybody.
 

5. One could reasonably doubt that it's a good idea to have a compiled-in  option to dump the entire trace of a
program'sinteraction with the  backend into a publicly readable temp file.  Can you say "security  hole"?  Seems to me
thatthis function should require a specific  request from the application, not be something that could accidentally
getinstalled as the default behavior of a system library.  (Think  what would happen if RPMs containing such behavior
gotdistributed...)
 

Perhaps something can be salvaged from the wreckage, but for now the
right answer is just to make sure that this code is not compiled.
        regards, tom lane


Re: libpq++ tracing considered harmful (was Re: libpq++ memory problems)

От
Lamar Owen
Дата:
Tom Lane wrote:
> Ah-hah, figured it out.  There *was* a recent relevant change, but the
> log message for it didn't say anything about leaks.  The problem is
> in the "debug" code for PgConnection, which in 6.5.* looks like:

[snip]

> 1. "DEBUG" is a symbol defined in the backend header files (it's a
>    severity level constant for elog()).  So although libpq++'s Makefile
>    thinks it can turn the code on or off via -DDEBUG, it's mistaken;
>    that debug-tracing code always gets compiled.
>    Oliver Elphick fixed that a month or so ago by changing the
>    controlling symbol to "DEBUGFILE".  So that's why you see the leak
>    in 6.5.3 and I don't see it in current sources.
> 4. If any tracing did occur, all of the output from (perhaps many)
>    different PgConnection objects in different program runs would all
>    get dumped into the same temp file, leaving it of doubtful use to
>    anybody.
> 5. One could reasonably doubt that it's a good idea to have a compiled-in
>    option to dump the entire trace of a program's interaction with the
>    backend into a publicly readable temp file.  Can you say "security
>    hole"?  Seems to me that this function should require a specific

Hmmmm..  

>    request from the application, not be something that could accidentally
>    get installed as the default behavior of a system library.  (Think
>    what would happen if RPMs containing such behavior got distributed...)

Yes, think of it.  How many other such 'surprises' lurk, I wonder?
> Perhaps something can be salvaged from the wreckage, but for now the
> right answer is just to make sure that this code is not compiled.

And to compile this code you supply _which_ configure option?  Which is
the default (which is how the RPMset is built)?  Or is this like one of
the many options in config.h.in (or config.h, depending on which side of
the configure divide you prefer to edit....), like so many other options
that aren't configure'able?

This is as good an argument as any for a single, canonical, RPMset as
I've seen in a while, Tom.  I (and others in the development group who
can help watchdog the RPMset) just have to be extra-diligent to make
sure stuff like compiling this freakish code doesn't happen.
--
Lamar Owen
WGCR Internet Radio
1 Peter 4:11


Re: libpq++ tracing considered harmful (was Re: libpq++ memory problems)

От
Tom Lane
Дата:
Lamar Owen <lamar.owen@wgcr.org> writes:
>> Perhaps something can be salvaged from the wreckage, but for now the
>> right answer is just to make sure that this code is not compiled.

> And to compile this code you supply _which_ configure option?

It isn't a configure option --- you have to edit libpq++'s makefile
to enable it.  Or, in the case of the 6.5.* code, it got turned on
anyway :-(.  Fortunately there is no security hole in either 6.5.*
or current, since the code is too broken to actually produce any
trace output, compiled or not.  My point was mainly that I thought
we should remove the code rather than fix it.
        regards, tom lane


Re: libpq++ tracing considered harmful (was Re: libpq++ memory problems)

От
Lamar Owen
Дата:
Tom Lane wrote:
> Lamar Owen <lamar.owen@wgcr.org> writes:
> >> Perhaps something can be salvaged from the wreckage, but for now the
> >> right answer is just to make sure that this code is not compiled.
> > And to compile this code you supply _which_ configure option?
> It isn't a configure option --- you have to edit libpq++'s makefile
> to enable it.  Or, in the case of the 6.5.* code, it got turned on
> anyway :-(.

Now that is just grand.  It will be a happy day once all the various
configuration options, both runtime and compiletime, are brought under
the GrandReUnification umbrella that Peter E is weaving right now....  

> Fortunately there is no security hole in either 6.5.*
> or current, since the code is too broken to actually produce any
> trace output, compiled or not.

That's what I thought you said.  Which, in this case, a bug was a good
thing -- as if the code hadn't been buggy, we'd have had a security bug.
~:-] 

> My point was mainly that I thought
> we should remove the code rather than fix it.

Who added the code in the first place?  Would anyone _need_ it? 
Otherwise, I agree -- _can_ it, if it's not too big of a change this
close to release (methinks not, but, you never know).

--
Lamar Owen
WGCR Internet Radio
1 Peter 4:11


Re: libpq++ tracing considered harmful (was Re: libpq++ memory problems)

От
Tom Lane
Дата:
Tim Brookes <tim.brookes@mcmail.com> writes:
> I have repeated my previous test, and found I am still leaking huge
> amounts of memory.

Hmph.  Are you sure you are releasing query results when you're done
with them?
        regards, tom lane


Re: libpq++ tracing considered harmful (was Re: libpq++ memory problems)

От
Tom Lane
Дата:
Tim Brookes <tim.brookes@mcmail.com> writes:
> The code is simply a constructor and destructor call of PgDatabase,
> called in succession, within an endless loop to emphasise the issue.
> But you're right, something isn't being released - within the
> destructor.

All I can say is, I see absolutely zero leakage with 7.0 code and the
attached test program.  Are you sure you didn't link a 6.5 library
by mistake, or something like that?
        regards, tom lane


#include <iostream.h>
#include <libpq++.h>

int main()
{ for (int i = 0; i < 10000; i++) {   // Open the connection to the database and make sure it's OK   PgDatabase
data("dbname=template1user=postgres");   if ( data.ConnectionBad() ) {     cout << "Connection was unsuccessful..." <<
endl         << "Error message returned: " << data.ErrorMessage() << endl;     return 1;   } } return 0;
 
} // End main()